diff --git a/pkg/yqlib/encoder_toml.go b/pkg/yqlib/encoder_toml.go index 12a6d828..ed4de4ec 100644 --- a/pkg/yqlib/encoder_toml.go +++ b/pkg/yqlib/encoder_toml.go @@ -184,9 +184,12 @@ func (te *tomlEncoder) encodeTopLevelEntry(w io.Writer, path []string, node *Can // Regular array attribute return te.writeArrayAttribute(w, path[len(path)-1], node) case MappingNode: - // Use inline table syntax for nodes explicitly marked as TOML inline tables - // or YAML flow mappings. All other mappings become readable TOML table sections. - if node.EncodeHint == EncodeHintInline || node.Style&FlowStyle != 0 { + // Use inline table syntax only for nodes explicitly marked as TOML inline tables. + // YAML flow-style mappings are not treated as inline tables; the FlowStyle attribute + // is a YAML-specific rendering hint and should not affect TOML output. This ensures + // that auto-detected JSON input (parsed as YAML flow style) produces readable table + // sections, consistent with explicitly parsed JSON input. + if node.EncodeHint == EncodeHintInline { return te.writeInlineTableAttribute(w, path[len(path)-1], node) } return te.encodeSeparateMapping(w, path, node) @@ -469,7 +472,7 @@ func (te *tomlEncoder) encodeSeparateMapping(w io.Writer, path []string, m *Cand hasAttrs = true break } - if v.Kind == MappingNode && (v.EncodeHint == EncodeHintInline || v.Style&FlowStyle != 0) { + if v.Kind == MappingNode && v.EncodeHint == EncodeHintInline { hasAttrs = true break } @@ -569,13 +572,13 @@ func (te *tomlEncoder) encodeMappingBodyWithPath(w io.Writer, path []string, m * } } - // Finally, child mappings: inline-hint or flow-style ones become inline table attributes, + // Finally, child mappings: inline-hint ones become inline table attributes, // while all others are emitted as separate sub-table sections. for i := 0; i < len(m.Content); i += 2 { k := m.Content[i].Value v := m.Content[i+1] if v.Kind == MappingNode { - if v.EncodeHint == EncodeHintInline || v.Style&FlowStyle != 0 { + if v.EncodeHint == EncodeHintInline { if err := te.writeInlineTableAttribute(w, k, v); err != nil { return err } diff --git a/pkg/yqlib/toml_test.go b/pkg/yqlib/toml_test.go index 2a54d331..c923d02b 100644 --- a/pkg/yqlib/toml_test.go +++ b/pkg/yqlib/toml_test.go @@ -707,11 +707,25 @@ var tomlScenarios = []formatScenario{ }, { skipDoc: true, - description: "Encode: YAML flow mapping stays inline", + description: "Encode: YAML flow mapping produces table section (same as block mapping)", input: "arg: {hello: foo}\n", - expected: "arg = { hello = \"foo\" }\n", + expected: "[arg]\nhello = \"foo\"\n", scenarioType: "encode", }, + { + skipDoc: true, + description: "Issue: JSON auto-detected via YAML decoder produces table sections", + input: `{"arg":{"hello": "foo"}}`, + expected: "[arg]\nhello = \"foo\"\n", + scenarioType: "encode", + }, + { + skipDoc: true, + description: "Issue: JSON via JSON decoder produces table sections", + input: `{"arg":{"hello": "foo"}}`, + expected: "[arg]\nhello = \"foo\"\n", + scenarioType: "encode-json", + }, { skipDoc: true, description: "Roundtrip: key with special characters in inline table", @@ -753,6 +767,8 @@ func testTomlScenario(t *testing.T, s formatScenario) { test.AssertResultWithContext(t, s.expected, mustProcessFormatScenario(s, NewTomlDecoder(), NewTomlEncoder()), s.description) case "encode": test.AssertResultWithContext(t, s.expected, mustProcessFormatScenario(s, NewYamlDecoder(ConfiguredYamlPreferences), NewTomlEncoder()), s.description) + case "encode-json": + test.AssertResultWithContext(t, s.expected, mustProcessFormatScenario(s, NewJSONDecoder(), NewTomlEncoder()), s.description) } } @@ -833,7 +849,7 @@ func documentTomlScenario(_ *testing.T, w *bufio.Writer, i interface{}) { documentTomlDecodeScenario(w, s) case "roundtrip": documentTomlRoundtripScenario(w, s) - case "encode": + case "encode", "encode-json": documentTomlEncodeScenario(w, s) default: