Files
libopenapi/json/json.go
2023-12-03 22:28:15 +00:00

90 lines
1.8 KiB
Go

package json
import (
"encoding/json"
"fmt"
"github.com/pb33f/libopenapi/orderedmap"
"gopkg.in/yaml.v3"
)
// YAMLNodeToJSON converts yaml/json stored in a yaml.Node to json ordered matching the original yaml/json
//
// NOTE: The limitation is this won't work with YAML that is not compatible with JSON, ie yaml with anchors or complex map keys
func YAMLNodeToJSON(node *yaml.Node, indentation string) ([]byte, error) {
v, err := handleYAMLNode(node)
if err != nil {
return nil, err
}
return json.MarshalIndent(v, "", indentation)
}
func handleYAMLNode(node *yaml.Node) (any, error) {
switch node.Kind {
case yaml.DocumentNode:
return handleYAMLNode(node.Content[0])
case yaml.SequenceNode:
return handleSequenceNode(node)
case yaml.MappingNode:
return handleMappingNode(node)
case yaml.ScalarNode:
return handleScalarNode(node)
case yaml.AliasNode:
panic("currently unsupported")
default:
return nil, fmt.Errorf("unknown node kind: %v", node.Kind)
}
}
func handleMappingNode(node *yaml.Node) (any, error) {
m := orderedmap.New[string, yaml.Node]()
if err := node.Decode(m); err != nil {
return nil, err
}
v := orderedmap.New[string, any]()
for pair := orderedmap.First(m); pair != nil; pair = pair.Next() {
n := pair.Value()
vv, err := handleYAMLNode(&n)
if err != nil {
return nil, err
}
v.Set(pair.Key(), vv)
}
return v, nil
}
func handleSequenceNode(node *yaml.Node) (any, error) {
var s []yaml.Node
if err := node.Decode(&s); err != nil {
return nil, err
}
v := make([]any, len(s))
for i, n := range s {
vv, err := handleYAMLNode(&n)
if err != nil {
return nil, err
}
v[i] = vv
}
return v, nil
}
func handleScalarNode(node *yaml.Node) (any, error) {
var v any
if err := node.Decode(&v); err != nil {
return nil, err
}
return v, nil
}