From 99b8b9705b3eacf3cc54e991df35802992017865 Mon Sep 17 00:00:00 2001 From: Lars Stegman Date: Thu, 20 Feb 2025 11:24:16 +0100 Subject: [PATCH 1/5] feat(marshal-goccy): marshal goccy structure --- pkg/yqlib/candidate_node_goccy_yaml.go | 152 ++++++++++++++++++++ pkg/yqlib/candidate_node_goccy_yaml_test.go | 43 ++++++ 2 files changed, 195 insertions(+) create mode 100644 pkg/yqlib/candidate_node_goccy_yaml_test.go diff --git a/pkg/yqlib/candidate_node_goccy_yaml.go b/pkg/yqlib/candidate_node_goccy_yaml.go index 89471f1846..5ab36ec9af 100644 --- a/pkg/yqlib/candidate_node_goccy_yaml.go +++ b/pkg/yqlib/candidate_node_goccy_yaml.go @@ -2,6 +2,7 @@ package yqlib import ( "fmt" + "strconv" "strings" yaml "github.com/goccy/go-yaml" @@ -205,3 +206,154 @@ func (o *CandidateNode) goccyProcessMappingValueNode(mappingEntry *ast.MappingVa return nil } + +func (o *CandidateNode) goccyMarshalChild(path string) (ast.Node, error) { + var node ast.Node + switch o.Kind { + case SequenceNode: + values := make([]ast.Node, len(o.Content)) + for i, content := range o.Content { + childNode, err := content.goccyMarshalChild(path + "[" + strconv.Itoa(i) + "]") + if err != nil { + return nil, err + } + + values[i] = childNode + } + + seq := ast.Sequence( + goccyToken.SequenceStart(o.Value, &goccyToken.Position{}), + o.Style == FlowStyle, + ) + + seq.Values = values + seq.ValueHeadComments = []*ast.CommentGroupNode{ast.CommentGroup([]*goccyToken.Token{goccyToken.Comment(o.HeadComment, o.HeadComment, &goccyToken.Position{})})} + seq.FootComment = goccyMarshalFootComment(o.FootComment) + node = seq + case MappingNode: + values := make([]*ast.MappingValueNode, len(o.Content)/2) + for i := 0; i < len(o.Content); i += 2 { + key, err := o.Content[i].goccyMarshalMapKeyNode(path) + if err != nil { + return nil, err + } + + value, err := o.Content[i+1].goccyMarshalChild(key.GetPath()) + if err != nil { + return nil, err + } + + childNode := ast.MappingValue( + goccyToken.MappingValue(&goccyToken.Position{}), + key, + value, + ) + childNode.SetPath(key.GetPath()) + if o.Content[i].FootComment != "" { + childNode.FootComment = goccyMarshalFootComment(o.Content[i].FootComment) + } + + values[i/2] = childNode + } + + mapping := ast.Mapping(goccyToken.MappingStart("", &goccyToken.Position{}), o.Style == FlowStyle, values...) + if o.FootComment != "" { + mapping.FootComment = goccyMarshalFootComment(o.FootComment) + } + + node = mapping + case ScalarNode: + v, err := o.GetValueRep() + if err != nil { + return nil, err + } + + node, err = o.goccyMarshalScalar(path, v) + if err != nil { + return nil, err + } + case AliasNode: + value, err := o.Content[0].goccyMarshalChild(path) + if err != nil { + return nil, err + } + + alias := ast.Alias(goccyToken.Alias(o.Value, &goccyToken.Position{})) + alias.Value = value + node = alias + } + + if o.Tag != "" && !strings.HasPrefix(o.Tag, "!!") { + tag := ast.Tag(goccyToken.Tag(o.Tag, o.Tag, &goccyToken.Position{})) + tag.Value = node + node = tag + } + + if o.Anchor != "" { + anc := ast.Anchor(goccyToken.Anchor(o.Anchor, &goccyToken.Position{})) + anc.Value = node + node = anc + } + + node.SetPath(path) + + return node, nil +} + +func (o *CandidateNode) MarshalGoccyYAML() (ast.Node, error) { + return o.goccyMarshalChild("$") +} + +func goccyMarshalFootComment(comment string) *ast.CommentGroupNode { + return ast.CommentGroup([]*goccyToken.Token{goccyToken.Comment(comment, comment, &goccyToken.Position{})}) +} + +func (o *CandidateNode) goccyMarshalMapKeyNode(path string) (ast.MapKeyNode, error) { + if o.Kind != ScalarNode { + return nil, fmt.Errorf("cannot unmarshal non-scalar node to MapKeyNode") + } + + v, err := o.GetValueRep() + if err != nil { + return nil, err + } + + key, err := o.goccyMarshalScalar(path, v) + if err != nil { + return nil, err + } + key.SetPath(path + "." + key.String()) + + return key, nil +} + +func (o *CandidateNode) goccyMarshalScalar(path string, v any) (ast.ScalarNode, error) { + t := goccyToken.Literal(o.Value, o.Value, &goccyToken.Position{}) + + if v == nil { + n := ast.Null(t) + n.SetPath(path) + return n, nil + } + + switch av := v.(type) { + case float64: + n := ast.Float(t) + n.Value = av + return n, nil + case int64: + n := ast.Integer(t) + n.Value = av + return n, nil + case bool: + n := ast.Bool(t) + n.Value = av + return n, nil + case string: + n := ast.String(t) + n.SetPath(path) + return n, nil + } + + return nil, fmt.Errorf("unknown scalar value type") +} diff --git a/pkg/yqlib/candidate_node_goccy_yaml_test.go b/pkg/yqlib/candidate_node_goccy_yaml_test.go new file mode 100644 index 0000000000..7ab12361d9 --- /dev/null +++ b/pkg/yqlib/candidate_node_goccy_yaml_test.go @@ -0,0 +1,43 @@ +package yqlib + +import ( + "fmt" + "testing" + + "gopkg.in/yaml.v3" +) + +func TestMarshalGoccyYAML(t *testing.T) { + input := ` +a: + b: 2 + c: &anc + d: !mytag ef + e: 3.0 +s: +- 1 +- 2 +` + + var yamlNode yaml.Node + err := yaml.Unmarshal([]byte(input), &yamlNode) + if err != nil { + t.Error(err) + return + } + + candidate := &CandidateNode{} + err = candidate.UnmarshalYAML(yamlNode.Content[0], make(map[string]*CandidateNode)) + if err != nil { + t.Error(err) + return + } + + goccyNode, err := candidate.MarshalGoccyYAML() + if err != nil { + t.Error(err) + return + } + + fmt.Println(goccyNode) +} From 3800c3a4f2cd9f05a65357ed6b8b3e6fea4b7af7 Mon Sep 17 00:00:00 2001 From: Lars Stegman Date: Thu, 15 May 2025 14:13:39 +0200 Subject: [PATCH 2/5] feat(goccy): marshal back to goccy ast --- pkg/yqlib/candidate_node_goccy_yaml.go | 238 +++++++++++++------- pkg/yqlib/candidate_node_goccy_yaml_test.go | 15 +- 2 files changed, 176 insertions(+), 77 deletions(-) diff --git a/pkg/yqlib/candidate_node_goccy_yaml.go b/pkg/yqlib/candidate_node_goccy_yaml.go index 5ab36ec9af..17541d3f74 100644 --- a/pkg/yqlib/candidate_node_goccy_yaml.go +++ b/pkg/yqlib/candidate_node_goccy_yaml.go @@ -207,82 +207,52 @@ func (o *CandidateNode) goccyProcessMappingValueNode(mappingEntry *ast.MappingVa return nil } -func (o *CandidateNode) goccyMarshalChild(path string) (ast.Node, error) { - var node ast.Node - switch o.Kind { - case SequenceNode: - values := make([]ast.Node, len(o.Content)) - for i, content := range o.Content { - childNode, err := content.goccyMarshalChild(path + "[" + strconv.Itoa(i) + "]") - if err != nil { - return nil, err - } - - values[i] = childNode - } - - seq := ast.Sequence( - goccyToken.SequenceStart(o.Value, &goccyToken.Position{}), - o.Style == FlowStyle, - ) - - seq.Values = values - seq.ValueHeadComments = []*ast.CommentGroupNode{ast.CommentGroup([]*goccyToken.Token{goccyToken.Comment(o.HeadComment, o.HeadComment, &goccyToken.Position{})})} - seq.FootComment = goccyMarshalFootComment(o.FootComment) - node = seq - case MappingNode: - values := make([]*ast.MappingValueNode, len(o.Content)/2) - for i := 0; i < len(o.Content); i += 2 { - key, err := o.Content[i].goccyMarshalMapKeyNode(path) - if err != nil { - return nil, err - } +func (o *CandidateNode) MarshalGoccyYAML() (ast.Node, error) { + marshaller := &goccyMarshaller{} + return marshaller.Marshal("$", o) +} - value, err := o.Content[i+1].goccyMarshalChild(key.GetPath()) - if err != nil { - return nil, err - } +type goccyMarshaller struct { + currentToken *goccyToken.Token +} - childNode := ast.MappingValue( - goccyToken.MappingValue(&goccyToken.Position{}), - key, - value, - ) - childNode.SetPath(key.GetPath()) - if o.Content[i].FootComment != "" { - childNode.FootComment = goccyMarshalFootComment(o.Content[i].FootComment) - } +func (m *goccyMarshaller) PushToken(t *goccyToken.Token) *goccyToken.Token { + if m.currentToken == nil { + m.currentToken = t + return m.currentToken + } - values[i/2] = childNode - } + m.currentToken.Next = t + t.Prev = m.currentToken + m.currentToken = t - mapping := ast.Mapping(goccyToken.MappingStart("", &goccyToken.Position{}), o.Style == FlowStyle, values...) - if o.FootComment != "" { - mapping.FootComment = goccyMarshalFootComment(o.FootComment) - } + return m.currentToken +} - node = mapping - case ScalarNode: - v, err := o.GetValueRep() +func (m *goccyMarshaller) Marshal(path string, o *CandidateNode) (ast.Node, error) { + var node ast.Node + var err error + switch o.Kind { + case AliasNode: + node, err = m.marshalAlias(path, o) if err != nil { return nil, err } - - node, err = o.goccyMarshalScalar(path, v) + case ScalarNode: + node, err = m.marshalScalar(path, o) if err != nil { return nil, err } - case AliasNode: - value, err := o.Content[0].goccyMarshalChild(path) + case SequenceNode: + node, err = m.marshalSequence(path, o) if err != nil { return nil, err } - - alias := ast.Alias(goccyToken.Alias(o.Value, &goccyToken.Position{})) - alias.Value = value - node = alias + case MappingNode: + node, err = m.marshalMapping(path, o) } + // TODO: Fix Tag and Anchor tokens if o.Tag != "" && !strings.HasPrefix(o.Tag, "!!") { tag := ast.Tag(goccyToken.Tag(o.Tag, o.Tag, &goccyToken.Position{})) tag.Value = node @@ -300,25 +270,136 @@ func (o *CandidateNode) goccyMarshalChild(path string) (ast.Node, error) { return node, nil } -func (o *CandidateNode) MarshalGoccyYAML() (ast.Node, error) { - return o.goccyMarshalChild("$") +func (m *goccyMarshaller) marshalAlias(path string, o *CandidateNode) (ast.Node, error) { + t := m.PushToken(goccyToken.Alias(o.Value, &goccyToken.Position{})) + var value ast.Node + var err error + value, err = m.Marshal(path, o.Content[0]) + if err != nil { + return nil, err + } + + alias := ast.Alias(t) + alias.Value = value + return alias, nil } -func goccyMarshalFootComment(comment string) *ast.CommentGroupNode { - return ast.CommentGroup([]*goccyToken.Token{goccyToken.Comment(comment, comment, &goccyToken.Position{})}) +func (m *goccyMarshaller) marshalSequence(path string, o *CandidateNode) (ast.Node, error) { + isFlowStyle := o.Style == FlowStyle + seq := ast.Sequence( + nil, + isFlowStyle, + ) + + if isFlowStyle { + seq.Start = m.PushToken(goccyToken.SequenceStart("[", &goccyToken.Position{})) + } + + var err error + values := make([]ast.Node, len(o.Content)) + for i, content := range o.Content { + m.PushToken(goccyToken.SequenceEntry("-", &goccyToken.Position{})) + values[i], err = m.Marshal(path+"["+strconv.Itoa(i)+"]", content) + if err != nil { + return nil, err + } + + if isFlowStyle && i < len(o.Content)-1 { + m.PushToken(goccyToken.CollectEntry(",", &goccyToken.Position{})) + } + } + + if isFlowStyle { + seq.End = m.PushToken(goccyToken.SequenceEnd("]", &goccyToken.Position{})) + } + + seq.Values = values + seq.ValueHeadComments = []*ast.CommentGroupNode{ast.CommentGroup([]*goccyToken.Token{goccyToken.Comment(o.HeadComment, o.HeadComment, &goccyToken.Position{})})} + seq.FootComment = goccyMarshalFootComment(o.FootComment) + + return seq, nil } -func (o *CandidateNode) goccyMarshalMapKeyNode(path string) (ast.MapKeyNode, error) { - if o.Kind != ScalarNode { - return nil, fmt.Errorf("cannot unmarshal non-scalar node to MapKeyNode") +func (m *goccyMarshaller) marshalMapping(path string, o *CandidateNode) (ast.Node, error) { + isFlowStyle := o.Style == FlowStyle + mapping := ast.Mapping(nil, isFlowStyle) + + if isFlowStyle { + mapping.Start = m.PushToken(goccyToken.MappingStart("{", &goccyToken.Position{})) } - v, err := o.GetValueRep() + values := make([]*ast.MappingValueNode, len(o.Content)/2) + var err error + for i := 0; i < len(o.Content); i += 2 { + var childNode *ast.MappingValueNode + childNode, err = m.marshalMappingValueNode(path, o.Content[i], o.Content[i+1]) + if err != nil { + return nil, err + } + + if o.Content[i].FootComment != "" { + childNode.FootComment = goccyMarshalFootComment(o.Content[i].FootComment) + } + + values[i/2] = childNode + if isFlowStyle && i < len(o.Content)/2-1 { + m.PushToken(goccyToken.CollectEntry(",", &goccyToken.Position{})) + } + } + + mapping.Values = values + + if !isFlowStyle && len(values) > 0 { + mapping.Start = values[0].Start + } + + if isFlowStyle { + mapping.End = m.PushToken(goccyToken.MappingEnd("}", &goccyToken.Position{})) + } + + if o.FootComment != "" { + mapping.FootComment = goccyMarshalFootComment(o.FootComment) + } + + return mapping, nil +} + +func (m *goccyMarshaller) marshalMappingValueNode(path string, keyNode, valueNode *CandidateNode) (*ast.MappingValueNode, error) { + var key ast.MapKeyNode + var err error + key, err = m.marshalMapKeyNode(path, keyNode) if err != nil { return nil, err } - key, err := o.goccyMarshalScalar(path, v) + separatorToken := m.PushToken(goccyToken.MappingValue(&goccyToken.Position{})) + + value, err := m.Marshal(key.GetPath(), valueNode) + if err != nil { + return nil, err + } + + childNode := ast.MappingValue( + separatorToken, + key, + value, + ) + childNode.SetPath(key.GetPath()) + + return childNode, nil +} + +func goccyMarshalFootComment(comment string) *ast.CommentGroupNode { + // TODO: Fix Tokens + return ast.CommentGroup([]*goccyToken.Token{goccyToken.Comment(comment, comment, &goccyToken.Position{})}) +} + +func (m *goccyMarshaller) marshalMapKeyNode(path string, o *CandidateNode) (ast.MapKeyNode, error) { + if o.Kind != ScalarNode { + return nil, fmt.Errorf("cannot unmarshal non-scalar node to MapKeyNode") + } + + key, err := m.marshalScalar(path, o) if err != nil { return nil, err } @@ -327,30 +408,35 @@ func (o *CandidateNode) goccyMarshalMapKeyNode(path string) (ast.MapKeyNode, err return key, nil } -func (o *CandidateNode) goccyMarshalScalar(path string, v any) (ast.ScalarNode, error) { - t := goccyToken.Literal(o.Value, o.Value, &goccyToken.Position{}) +func (m *goccyMarshaller) marshalScalar(path string, o *CandidateNode) (ast.ScalarNode, error) { + v, err := o.GetValueRep() + if err != nil { + return nil, err + } + + scalarToken := m.PushToken(goccyToken.Literal(o.Value, o.Value, &goccyToken.Position{})) if v == nil { - n := ast.Null(t) + n := ast.Null(scalarToken) n.SetPath(path) return n, nil } switch av := v.(type) { case float64: - n := ast.Float(t) + n := ast.Float(scalarToken) n.Value = av return n, nil case int64: - n := ast.Integer(t) + n := ast.Integer(scalarToken) n.Value = av return n, nil case bool: - n := ast.Bool(t) + n := ast.Bool(scalarToken) n.Value = av return n, nil case string: - n := ast.String(t) + n := ast.String(scalarToken) n.SetPath(path) return n, nil } diff --git a/pkg/yqlib/candidate_node_goccy_yaml_test.go b/pkg/yqlib/candidate_node_goccy_yaml_test.go index 7ab12361d9..ed311435cd 100644 --- a/pkg/yqlib/candidate_node_goccy_yaml_test.go +++ b/pkg/yqlib/candidate_node_goccy_yaml_test.go @@ -4,6 +4,7 @@ import ( "fmt" "testing" + "github.com/goccy/go-yaml/parser" "gopkg.in/yaml.v3" ) @@ -17,10 +18,15 @@ a: s: - 1 - 2 +t: [5, five] +f: [6, {y: true}] ` + goccyAst, err := parser.ParseBytes([]byte(input), parser.ParseComments) + fmt.Println(goccyAst) + var yamlNode yaml.Node - err := yaml.Unmarshal([]byte(input), &yamlNode) + err = yaml.Unmarshal([]byte(input), &yamlNode) if err != nil { t.Error(err) return @@ -39,5 +45,12 @@ s: return } + parsed, err := parser.ParseBytes([]byte(input), parser.ParseComments) + if err != nil { + t.Error(err) + return + } + + fmt.Println(parsed) fmt.Println(goccyNode) } From c573d2a63bd2384db8d91f2704f6d8249139117c Mon Sep 17 00:00:00 2001 From: Lars Stegman Date: Mon, 19 May 2025 11:30:23 +0200 Subject: [PATCH 3/5] fix: don't overwrite value --- pkg/yqlib/candidate_node_goccy_yaml.go | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/pkg/yqlib/candidate_node_goccy_yaml.go b/pkg/yqlib/candidate_node_goccy_yaml.go index 17541d3f74..b71bf59154 100644 --- a/pkg/yqlib/candidate_node_goccy_yaml.go +++ b/pkg/yqlib/candidate_node_goccy_yaml.go @@ -422,21 +422,19 @@ func (m *goccyMarshaller) marshalScalar(path string, o *CandidateNode) (ast.Scal return n, nil } - switch av := v.(type) { + var n ast.ScalarNode + switch v.(type) { case float64: - n := ast.Float(scalarToken) - n.Value = av - return n, nil + n = ast.Float(scalarToken) case int64: - n := ast.Integer(scalarToken) - n.Value = av - return n, nil + n = ast.Integer(scalarToken) case bool: - n := ast.Bool(scalarToken) - n.Value = av - return n, nil + n = ast.Bool(scalarToken) case string: - n := ast.String(scalarToken) + n = ast.String(scalarToken) + } + + if n != nil { n.SetPath(path) return n, nil } From 807ccfbe53d73ecdcd431c96d6b1f057b2d14839 Mon Sep 17 00:00:00 2001 From: Lars Stegman Date: Tue, 17 Jun 2025 11:32:50 +0200 Subject: [PATCH 4/5] feat(parser): include positions --- pkg/yqlib/candidate_node_goccy_yaml.go | 30 ++++++++++++++++++++------ 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/pkg/yqlib/candidate_node_goccy_yaml.go b/pkg/yqlib/candidate_node_goccy_yaml.go index b71bf59154..e13f92de24 100644 --- a/pkg/yqlib/candidate_node_goccy_yaml.go +++ b/pkg/yqlib/candidate_node_goccy_yaml.go @@ -270,8 +270,15 @@ func (m *goccyMarshaller) Marshal(path string, o *CandidateNode) (ast.Node, erro return node, nil } +func (_ *goccyMarshaller) getPosition(o *CandidateNode) *goccyToken.Position { + return &goccyToken.Position{ + Line: o.Line, + Column: o.Column, + } +} + func (m *goccyMarshaller) marshalAlias(path string, o *CandidateNode) (ast.Node, error) { - t := m.PushToken(goccyToken.Alias(o.Value, &goccyToken.Position{})) + t := m.PushToken(goccyToken.Alias(o.Value, m.getPosition(o))) var value ast.Node var err error value, err = m.Marshal(path, o.Content[0]) @@ -298,7 +305,14 @@ func (m *goccyMarshaller) marshalSequence(path string, o *CandidateNode) (ast.No var err error values := make([]ast.Node, len(o.Content)) for i, content := range o.Content { - m.PushToken(goccyToken.SequenceEntry("-", &goccyToken.Position{})) + if !isFlowStyle { + entryToken := goccyToken.SequenceEntry("-", &goccyToken.Position{Line: content.Line, Column: o.Column}) + m.PushToken(entryToken) + if seq.Start == nil { + seq.Start = entryToken + } + } + values[i], err = m.Marshal(path+"["+strconv.Itoa(i)+"]", content) if err != nil { return nil, err @@ -315,7 +329,9 @@ func (m *goccyMarshaller) marshalSequence(path string, o *CandidateNode) (ast.No seq.Values = values seq.ValueHeadComments = []*ast.CommentGroupNode{ast.CommentGroup([]*goccyToken.Token{goccyToken.Comment(o.HeadComment, o.HeadComment, &goccyToken.Position{})})} - seq.FootComment = goccyMarshalFootComment(o.FootComment) + if o.FootComment != "" { + seq.FootComment = goccyMarshalFootComment(o.FootComment) + } return seq, nil } @@ -332,7 +348,7 @@ func (m *goccyMarshaller) marshalMapping(path string, o *CandidateNode) (ast.Nod var err error for i := 0; i < len(o.Content); i += 2 { var childNode *ast.MappingValueNode - childNode, err = m.marshalMappingValueNode(path, o.Content[i], o.Content[i+1]) + childNode, err = m.marshalMappingValueNode(path, o, o.Content[i], o.Content[i+1]) if err != nil { return nil, err } @@ -364,7 +380,7 @@ func (m *goccyMarshaller) marshalMapping(path string, o *CandidateNode) (ast.Nod return mapping, nil } -func (m *goccyMarshaller) marshalMappingValueNode(path string, keyNode, valueNode *CandidateNode) (*ast.MappingValueNode, error) { +func (m *goccyMarshaller) marshalMappingValueNode(path string, entryNode, keyNode, valueNode *CandidateNode) (*ast.MappingValueNode, error) { var key ast.MapKeyNode var err error key, err = m.marshalMapKeyNode(path, keyNode) @@ -372,7 +388,7 @@ func (m *goccyMarshaller) marshalMappingValueNode(path string, keyNode, valueNod return nil, err } - separatorToken := m.PushToken(goccyToken.MappingValue(&goccyToken.Position{})) + separatorToken := m.PushToken(goccyToken.MappingValue(m.getPosition(entryNode))) value, err := m.Marshal(key.GetPath(), valueNode) if err != nil { @@ -414,7 +430,7 @@ func (m *goccyMarshaller) marshalScalar(path string, o *CandidateNode) (ast.Scal return nil, err } - scalarToken := m.PushToken(goccyToken.Literal(o.Value, o.Value, &goccyToken.Position{})) + scalarToken := m.PushToken(goccyToken.Literal(o.Value, o.Value, m.getPosition(o))) if v == nil { n := ast.Null(scalarToken) From b966ccc107c621179c10e5aea11d23fc95e2e39e Mon Sep 17 00:00:00 2001 From: Lars Stegman Date: Tue, 17 Jun 2025 16:05:17 +0200 Subject: [PATCH 5/5] feat(parser): fix MappingValue position --- pkg/yqlib/candidate_node_goccy_yaml.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pkg/yqlib/candidate_node_goccy_yaml.go b/pkg/yqlib/candidate_node_goccy_yaml.go index e13f92de24..29e956623c 100644 --- a/pkg/yqlib/candidate_node_goccy_yaml.go +++ b/pkg/yqlib/candidate_node_goccy_yaml.go @@ -341,7 +341,7 @@ func (m *goccyMarshaller) marshalMapping(path string, o *CandidateNode) (ast.Nod mapping := ast.Mapping(nil, isFlowStyle) if isFlowStyle { - mapping.Start = m.PushToken(goccyToken.MappingStart("{", &goccyToken.Position{})) + mapping.Start = m.PushToken(goccyToken.MappingStart("{", m.getPosition(o))) } values := make([]*ast.MappingValueNode, len(o.Content)/2) @@ -388,7 +388,10 @@ func (m *goccyMarshaller) marshalMappingValueNode(path string, entryNode, keyNod return nil, err } - separatorToken := m.PushToken(goccyToken.MappingValue(m.getPosition(entryNode))) + separatorToken := m.PushToken(goccyToken.MappingValue(&goccyToken.Position{ + Line: key.GetToken().Position.Line, + Column: key.GetToken().Position.Column + len(key.String()), + })) value, err := m.Marshal(key.GetPath(), valueNode) if err != nil {