mirror of
https://github.com/mikefarah/yq.git
synced 2024-12-19 20:19:04 +00:00
Fixed json decode to maintain key order
This commit is contained in:
parent
a91a8ccc66
commit
2c9b5be408
@ -22,13 +22,13 @@ func (dec *jsonDecoder) Init(reader io.Reader) {
|
|||||||
|
|
||||||
func (dec *jsonDecoder) Decode(rootYamlNode *yaml.Node) error {
|
func (dec *jsonDecoder) Decode(rootYamlNode *yaml.Node) error {
|
||||||
|
|
||||||
var dataBucket interface{}
|
var dataBucket orderedMap
|
||||||
log.Debug("going to decode")
|
log.Debug("going to decode")
|
||||||
err := dec.decoder.Decode(&dataBucket)
|
err := dec.decoder.Decode(&dataBucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
node, err := dec.convertToYamlNode(dataBucket)
|
node, err := dec.convertToYamlNode(&dataBucket)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -38,39 +38,36 @@ func (dec *jsonDecoder) Decode(rootYamlNode *yaml.Node) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dec *jsonDecoder) convertToYamlNode(data interface{}) (*yaml.Node, error) {
|
func (dec *jsonDecoder) convertToYamlNode(data *orderedMap) (*yaml.Node, error) {
|
||||||
switch data := data.(type) {
|
if data.kv == nil {
|
||||||
case nil:
|
switch rawData := data.altVal.(type) {
|
||||||
return createScalarNode(nil, "null"), nil
|
case nil:
|
||||||
case float64, float32:
|
return createScalarNode(nil, "null"), nil
|
||||||
// json decoder returns ints as float.
|
case float64, float32:
|
||||||
return parseSnippet(fmt.Sprintf("%v", data))
|
// json decoder returns ints as float.
|
||||||
case int, int64, int32, string, bool:
|
return parseSnippet(fmt.Sprintf("%v", rawData))
|
||||||
return createScalarNode(data, fmt.Sprintf("%v", data)), nil
|
case int, int64, int32, string, bool:
|
||||||
case map[string]interface{}:
|
return createScalarNode(rawData, fmt.Sprintf("%v", rawData)), nil
|
||||||
return dec.parseMap(data)
|
case []*orderedMap:
|
||||||
case []interface{}:
|
return dec.parseArray(rawData)
|
||||||
return dec.parseArray(data)
|
default:
|
||||||
default:
|
return nil, fmt.Errorf("unrecognised type :( %v", rawData)
|
||||||
return nil, fmt.Errorf("unrecognised type :(")
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func (dec *jsonDecoder) parseMap(dataMap map[string]interface{}) (*yaml.Node, error) {
|
|
||||||
|
|
||||||
var yamlMap = &yaml.Node{Kind: yaml.MappingNode}
|
var yamlMap = &yaml.Node{Kind: yaml.MappingNode}
|
||||||
|
for _, keyValuePair := range data.kv {
|
||||||
for key, value := range dataMap {
|
yamlValue, err := dec.convertToYamlNode(&keyValuePair.V)
|
||||||
yamlValue, err := dec.convertToYamlNode(value)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
yamlMap.Content = append(yamlMap.Content, createScalarNode(key, fmt.Sprintf("%v", key)), yamlValue)
|
yamlMap.Content = append(yamlMap.Content, createScalarNode(keyValuePair.K, keyValuePair.K), yamlValue)
|
||||||
}
|
}
|
||||||
return yamlMap, nil
|
return yamlMap, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dec *jsonDecoder) parseArray(dataArray []interface{}) (*yaml.Node, error) {
|
func (dec *jsonDecoder) parseArray(dataArray []*orderedMap) (*yaml.Node, error) {
|
||||||
|
|
||||||
var yamlMap = &yaml.Node{Kind: yaml.SequenceNode}
|
var yamlMap = &yaml.Node{Kind: yaml.SequenceNode}
|
||||||
|
|
||||||
|
@ -66,8 +66,13 @@ func (o *orderedMap) UnmarshalJSON(data []byte) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
case '[':
|
case '[':
|
||||||
var arr []orderedMap
|
var res []*orderedMap
|
||||||
return json.Unmarshal(data, &arr)
|
if err := json.Unmarshal(data, &res); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
o.altVal = res
|
||||||
|
o.kv = nil
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return json.Unmarshal(data, &o.altVal)
|
return json.Unmarshal(data, &o.altVal)
|
||||||
|
@ -22,6 +22,13 @@ const sampleNdJson = `{"this": "is a multidoc json file"}
|
|||||||
{"a number": 4}
|
{"a number": 4}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const sampleNdJsonKey = `{"a": "first", "b": "next", "ab": "last"}`
|
||||||
|
|
||||||
|
const expectedJsonKeysInOrder = `a: first
|
||||||
|
b: next
|
||||||
|
ab: last
|
||||||
|
`
|
||||||
|
|
||||||
const expectedNdJsonYaml = `this: is a multidoc json file
|
const expectedNdJsonYaml = `this: is a multidoc json file
|
||||||
---
|
---
|
||||||
each:
|
each:
|
||||||
@ -157,6 +164,13 @@ var jsonScenarios = []formatScenario{
|
|||||||
expected: expectedNdJsonYaml,
|
expected: expectedNdJsonYaml,
|
||||||
scenarioType: "decode-ndjson",
|
scenarioType: "decode-ndjson",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
description: "Decode NDJSON, maintain key order",
|
||||||
|
skipDoc: true,
|
||||||
|
input: sampleNdJsonKey,
|
||||||
|
expected: expectedJsonKeysInOrder,
|
||||||
|
scenarioType: "decode-ndjson",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
description: "numbers",
|
description: "numbers",
|
||||||
skipDoc: true,
|
skipDoc: true,
|
||||||
@ -164,6 +178,20 @@ var jsonScenarios = []formatScenario{
|
|||||||
expected: "- 3\n- 3\n- 3.1\n- -1\n",
|
expected: "- 3\n- 3\n- 3.1\n- -1\n",
|
||||||
scenarioType: "decode-ndjson",
|
scenarioType: "decode-ndjson",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
description: "number single",
|
||||||
|
skipDoc: true,
|
||||||
|
input: "3",
|
||||||
|
expected: "3\n",
|
||||||
|
scenarioType: "decode-ndjson",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "empty string",
|
||||||
|
skipDoc: true,
|
||||||
|
input: `""`,
|
||||||
|
expected: "\"\"\n",
|
||||||
|
scenarioType: "decode-ndjson",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
description: "strings",
|
description: "strings",
|
||||||
skipDoc: true,
|
skipDoc: true,
|
||||||
|
Loading…
Reference in New Issue
Block a user