kin-openapi icon indicating copy to clipboard operation
kin-openapi copied to clipboard

Use goccy/go-yaml instead of invopop/yaml?

Open renom opened this issue 2 years ago • 4 comments

https://github.com/goccy/go-yaml The library preserves the order of fields when converting from YAML It should fix deepmap/oapi-codegen#458

renom avatar Oct 19 '23 14:10 renom

@renom if I use yaml.Marshal(&base) (goccy) paths are empty.

If I do:

b, err := json.Marshal(&base)
	if err != nil {
		return fmt.Errorf("marshalling base: %w", err)
	}

	b, err = yaml.JSONToYAML(b)
	if err != nil {
		return fmt.Errorf("converting to yaml: %w", err)
	}

I get paths but order is lost. Am I using it wrong?

sonu27 avatar Feb 05 '24 09:02 sonu27

I'm not sure if I understand your question correctly. I'll write what I've found out since I opened the issue.

  1. To preserve the order of fields, you need to use goccy's type MapSlice instead of a regular map: https://github.com/goccy/go-yaml/blob/master/yaml.go#L68

For example:

struct {
	Map map[string]string
}

Should become:

struct {
	Map yaml.MapSlice
}
  1. MapSlice is an ordered version of map[any]any. So if you wanna have an equivalent of something like map[string]int or map[string]struct{}, it isn't supported unless you convert it to MapSlice (an equivalent of map[any]any).
  2. I've created an issue that suggests supporting a generic MapSlice (e.g. MapSlice[string, SpecificMapValue]): https://github.com/goccy/go-yaml/issues/422 Still hasn't got a response though.

renom avatar Feb 05 '24 13:02 renom

I can't use a map, I'm trying to convert an openapi type struct. e.g.

// T is the root of an OpenAPI v3 document
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#openapi-object
type T struct {
	Extensions map[string]interface{} `json:"-" yaml:"-"`

	OpenAPI      string               `json:"openapi" yaml:"openapi"` // Required
	Components   *Components          `json:"components,omitempty" yaml:"components,omitempty"`
	Info         *Info                `json:"info" yaml:"info"`   // Required
	Paths        *Paths               `json:"paths" yaml:"paths"` // Required
	Security     SecurityRequirements `json:"security,omitempty" yaml:"security,omitempty"`
	Servers      Servers              `json:"servers,omitempty" yaml:"servers,omitempty"`
	Tags         Tags                 `json:"tags,omitempty" yaml:"tags,omitempty"`
	ExternalDocs *ExternalDocs        `json:"externalDocs,omitempty" yaml:"externalDocs,omitempty"`

	visited visitedComponent
}

Which has it's own MarshalJSON method, which then I convert to yaml.

sonu27 avatar Feb 06 '24 10:02 sonu27

I'm thinking generic MapSlice would be a better struct that the one I use in https://github.com/getkin/kin-openapi/pull/695

@renom can you share your experience using MapSlice? What do you think of using this as the go-to map[_]_ within the lib?

fenollp avatar Mar 22 '24 19:03 fenollp