mirror of
https://github.com/mikefarah/yq.git
synced 2026-08-24 08:22:13 +08:00
Fix typo in filename (#2611)
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
//go:build !yq_nojson
|
||||
|
||||
package yqlib
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/goccy/go-json"
|
||||
)
|
||||
|
||||
func (o *CandidateNode) setScalarFromJson(value interface{}) error {
|
||||
o.Kind = ScalarNode
|
||||
switch rawData := value.(type) {
|
||||
case nil:
|
||||
o.Tag = "!!null"
|
||||
o.Value = "null"
|
||||
case float64, float32:
|
||||
o.Value = fmt.Sprintf("%v", value)
|
||||
o.Tag = "!!float"
|
||||
// json decoder returns ints as float.
|
||||
if value == float64(int64(rawData.(float64))) {
|
||||
// aha it's an int disguised as a float
|
||||
o.Tag = "!!int"
|
||||
o.Value = fmt.Sprintf("%v", int64(value.(float64)))
|
||||
}
|
||||
case int, int64, int32:
|
||||
o.Value = fmt.Sprintf("%v", value)
|
||||
o.Tag = "!!int"
|
||||
case bool:
|
||||
o.Value = fmt.Sprintf("%v", value)
|
||||
o.Tag = "!!bool"
|
||||
case string:
|
||||
o.Value = rawData
|
||||
o.Tag = "!!str"
|
||||
default:
|
||||
return fmt.Errorf("unrecognised type :( %v", rawData)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *CandidateNode) UnmarshalJSON(data []byte) error {
|
||||
log.Debug("UnmarshalJSON")
|
||||
switch data[0] {
|
||||
case '{':
|
||||
log.Debug("UnmarshalJSON - its a map!")
|
||||
// its a map
|
||||
o.Kind = MappingNode
|
||||
o.Tag = "!!map"
|
||||
|
||||
dec := json.NewDecoder(bytes.NewReader(data))
|
||||
_, err := dec.Token() // open object
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// cycle through k/v
|
||||
var tok json.Token
|
||||
for tok, err = dec.Token(); err == nil; tok, err = dec.Token() {
|
||||
// we can expect two types: string or Delim. Delim automatically means
|
||||
// that it is the closing bracket of the object, whereas string means
|
||||
// that there is another key.
|
||||
if _, ok := tok.(json.Delim); ok {
|
||||
break
|
||||
}
|
||||
|
||||
childKey := o.CreateChild()
|
||||
childKey.IsMapKey = true
|
||||
childKey.Value = tok.(string)
|
||||
childKey.Kind = ScalarNode
|
||||
childKey.Tag = "!!str"
|
||||
|
||||
childValue := o.CreateChild()
|
||||
childValue.Key = childKey
|
||||
|
||||
if err := dec.Decode(childValue); err != nil {
|
||||
return err
|
||||
}
|
||||
o.Content = append(o.Content, childKey, childValue)
|
||||
}
|
||||
// unexpected error
|
||||
if err != nil && !errors.Is(err, io.EOF) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
case '[':
|
||||
o.Kind = SequenceNode
|
||||
o.Tag = "!!seq"
|
||||
log.Debug("UnmarshalJSON - its an array!")
|
||||
var children []*CandidateNode
|
||||
if err := json.Unmarshal(data, &children); err != nil {
|
||||
return err
|
||||
}
|
||||
// now we put the children into the content, and set a key value for them
|
||||
for i, child := range children {
|
||||
|
||||
if child == nil {
|
||||
// need to represent it as a null scalar
|
||||
child = createScalarNode(nil, "null")
|
||||
}
|
||||
childKey := o.CreateChild()
|
||||
childKey.Kind = ScalarNode
|
||||
childKey.Tag = "!!int"
|
||||
childKey.Value = fmt.Sprintf("%v", i)
|
||||
childKey.IsMapKey = true
|
||||
|
||||
child.Parent = o
|
||||
child.Key = childKey
|
||||
o.Content = append(o.Content, child)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
log.Debug("UnmarshalJSON - its a scalar!")
|
||||
// otherwise, must be a scalar
|
||||
var scalar interface{}
|
||||
err := json.Unmarshal(data, &scalar)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Debug("UnmarshalJSON - scalar is %v", scalar)
|
||||
|
||||
return o.setScalarFromJson(scalar)
|
||||
|
||||
}
|
||||
|
||||
func (o *CandidateNode) MarshalJSON() ([]byte, error) {
|
||||
log.Debugf("MarshalJSON %v", NodeToString(o))
|
||||
buf := new(bytes.Buffer)
|
||||
enc := json.NewEncoder(buf)
|
||||
enc.SetIndent("", " ")
|
||||
enc.SetEscapeHTML(false) // do not escape html chars e.g. &, <, >
|
||||
|
||||
switch o.Kind {
|
||||
case AliasNode:
|
||||
log.Debugf("MarshalJSON AliasNode")
|
||||
err := enc.Encode(o.Alias)
|
||||
return buf.Bytes(), err
|
||||
case ScalarNode:
|
||||
log.Debugf("MarshalJSON ScalarNode")
|
||||
value, err := o.GetValueRep()
|
||||
if err != nil {
|
||||
return buf.Bytes(), err
|
||||
}
|
||||
err = enc.Encode(value)
|
||||
return buf.Bytes(), err
|
||||
case MappingNode:
|
||||
log.Debugf("MarshalJSON MappingNode")
|
||||
buf.WriteByte('{')
|
||||
for i := 0; i < len(o.Content); i += 2 {
|
||||
if err := enc.Encode(o.Content[i].Value); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buf.WriteByte(':')
|
||||
if err := enc.Encode(o.Content[i+1]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if i != len(o.Content)-2 {
|
||||
buf.WriteByte(',')
|
||||
}
|
||||
}
|
||||
buf.WriteByte('}')
|
||||
return buf.Bytes(), nil
|
||||
case SequenceNode:
|
||||
log.Debugf("MarshalJSON SequenceNode, %v, len: %v", o.Content, len(o.Content))
|
||||
var err error
|
||||
if len(o.Content) == 0 {
|
||||
buf.WriteString("[]")
|
||||
} else {
|
||||
err = enc.Encode(o.Content)
|
||||
}
|
||||
return buf.Bytes(), err
|
||||
default:
|
||||
err := enc.Encode(nil)
|
||||
return buf.Bytes(), err
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user