Daniel
Daniel

Reputation: 23

Why golang yaml head comment becomes foot comment after unmarshal

I am testing with HeadComment from a very simple code below:

package main

import (
    "fmt"
    "gopkg.in/yaml.v3"
)

type Person struct {
    Name *yaml.Node
}

func main() {
    nameNode := &yaml.Node{
        Kind:        yaml.ScalarNode,
        HeadComment: "The name of a person",
        Value:       "Lily",
        Style: yaml.DoubleQuotedStyle,
    }

    person := Person{
        Name: nameNode,
    }

    dataInBytes, _ := yaml.Marshal(person)
    fmt.Println(string(dataInBytes))
}

I am expecting to see the output like this:

# The name of a person
name: "Lily"

However, I got:

name: "Lily"
# The name of a person

A head comment becomes a foot comment. Anyone has ideas ? Thanks !

https://play.golang.org/p/10bQt2KTKBU

Upvotes: 2

Views: 752

Answers (1)

blami
blami

Reputation: 7431

It happens because that head comment is attached to the value node (not name:, but "Lily") in YAML document tree.

So when events are being emitted that comment in fact belongs:

name: "Lily"
     ^-- here

It kinda makes sense that go-yaml puts header comment for value at the end of pair. Rather than expected behavior I'd call that implementation, so it's good that you've already opened a ticket with author of library to see whether they want to change implementation and move the head comment of value in key: value pair to position of header comment of key instead (I agree, specially in case when used to marshal struct this makes sense and is more handy).

Here is an example of code that creates same structure and adds head comment to name: key instead to get proper rendering (at cost of losing nice struct):

func main() {
        key := &yaml.Node{
                Kind:        yaml.ScalarNode,
                Value:       "name",
                HeadComment: "The name of a person",
        }
        value := &yaml.Node{
                Kind:  yaml.ScalarNode,
                Value: "Lilly",
                Style: yaml.DoubleQuotedStyle,
        }

        mapping := &yaml.Node{
                Kind:    yaml.MappingNode,
                Content: []*yaml.Node{key, value},
        }

        dataInBytes, _ := yaml.Marshal(mapping)
        fmt.Println(string(dataInBytes))
}

Output:

# The name of a person
name: "Lilly"

Upvotes: 2

Related Questions