2020-01-10 11:01:59 +00:00
|
|
|
package yqlib
|
|
|
|
|
|
|
|
import (
|
2020-02-27 23:09:49 +00:00
|
|
|
"bytes"
|
2020-01-10 11:01:59 +00:00
|
|
|
"encoding/json"
|
|
|
|
"io"
|
|
|
|
|
|
|
|
yaml "gopkg.in/yaml.v3"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Encoder interface {
|
|
|
|
Encode(node *yaml.Node) error
|
|
|
|
}
|
|
|
|
|
|
|
|
type yamlEncoder struct {
|
2020-02-27 23:09:49 +00:00
|
|
|
destination io.Writer
|
|
|
|
indent int
|
|
|
|
colorise bool
|
|
|
|
firstDoc bool
|
2020-01-10 11:01:59 +00:00
|
|
|
}
|
|
|
|
|
2020-02-27 23:09:49 +00:00
|
|
|
func NewYamlEncoder(destination io.Writer, indent int, colorise bool) Encoder {
|
2020-02-03 05:52:12 +00:00
|
|
|
if indent < 0 {
|
|
|
|
indent = 0
|
|
|
|
}
|
2020-02-27 23:09:49 +00:00
|
|
|
return &yamlEncoder{destination, indent, colorise, true}
|
2020-01-10 11:01:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (ye *yamlEncoder) Encode(node *yaml.Node) error {
|
2020-02-27 23:09:49 +00:00
|
|
|
|
|
|
|
destination := ye.destination
|
|
|
|
tempBuffer := bytes.NewBuffer(nil)
|
|
|
|
if ye.colorise {
|
|
|
|
destination = tempBuffer
|
|
|
|
}
|
|
|
|
|
|
|
|
var encoder = yaml.NewEncoder(destination)
|
|
|
|
|
|
|
|
encoder.SetIndent(ye.indent)
|
|
|
|
// TODO: work out if the first doc had a separator or not.
|
|
|
|
if ye.firstDoc {
|
|
|
|
ye.firstDoc = false
|
|
|
|
} else if _, err := destination.Write([]byte("---\n")); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := encoder.Encode(node); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if ye.colorise {
|
|
|
|
return ColorizeAndPrint(tempBuffer.Bytes(), ye.destination)
|
|
|
|
}
|
|
|
|
return nil
|
2020-01-10 11:01:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type jsonEncoder struct {
|
|
|
|
encoder *json.Encoder
|
|
|
|
}
|
|
|
|
|
2020-09-13 00:44:11 +00:00
|
|
|
func mapKeysToStrings(node *yaml.Node) {
|
2020-09-13 00:59:40 +00:00
|
|
|
|
2020-09-13 00:44:11 +00:00
|
|
|
if node.Kind == yaml.MappingNode {
|
|
|
|
for index, child := range node.Content {
|
2020-09-13 00:59:40 +00:00
|
|
|
if index%2 == 0 { // its a map key
|
2020-09-13 00:44:11 +00:00
|
|
|
child.Tag = "!!str"
|
|
|
|
}
|
2020-09-13 00:59:40 +00:00
|
|
|
}
|
2020-09-13 00:44:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, child := range node.Content {
|
|
|
|
mapKeysToStrings(child)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-03 05:52:12 +00:00
|
|
|
func NewJsonEncoder(destination io.Writer, prettyPrint bool, indent int) Encoder {
|
2020-01-10 11:01:59 +00:00
|
|
|
var encoder = json.NewEncoder(destination)
|
2020-02-03 05:52:12 +00:00
|
|
|
var indentString = ""
|
|
|
|
|
|
|
|
for index := 0; index < indent; index++ {
|
|
|
|
indentString = indentString + " "
|
|
|
|
}
|
2020-02-03 05:31:03 +00:00
|
|
|
if prettyPrint {
|
2020-02-03 05:52:12 +00:00
|
|
|
encoder.SetIndent("", indentString)
|
2020-02-03 05:31:03 +00:00
|
|
|
}
|
2020-01-10 11:01:59 +00:00
|
|
|
return &jsonEncoder{encoder}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (je *jsonEncoder) Encode(node *yaml.Node) error {
|
|
|
|
var dataBucket interface{}
|
2020-09-13 00:44:11 +00:00
|
|
|
// firstly, convert all map keys to strings
|
|
|
|
mapKeysToStrings(node)
|
2020-01-10 11:01:59 +00:00
|
|
|
errorDecoding := node.Decode(&dataBucket)
|
|
|
|
if errorDecoding != nil {
|
|
|
|
return errorDecoding
|
|
|
|
}
|
|
|
|
return je.encoder.Encode(dataBucket)
|
|
|
|
}
|