This commit is contained in:
Mike Farah 2023-04-03 22:25:37 +10:00
parent 54f5c9ee2f
commit 52b364ec52
6 changed files with 67 additions and 60 deletions

View File

@ -7,7 +7,6 @@ import (
"io"
"github.com/goccy/go-json"
yaml "gopkg.in/yaml.v3"
)
type jsonDecoder struct {
@ -38,14 +37,12 @@ func (dec *jsonDecoder) Decode() (*CandidateNode, error) {
}
return &CandidateNode{
Node: &yaml.Node{
Kind: yaml.DocumentNode,
Content: []*yaml.Node{node},
},
Kind: DocumentNode,
Content: []*CandidateNode{node},
}, nil
}
func (dec *jsonDecoder) convertToYamlNode(data *orderedMap) (*yaml.Node, error) {
func (dec *jsonDecoder) convertToYamlNode(data *orderedMap) (*CandidateNode, error) {
if data.kv == nil {
switch rawData := data.altVal.(type) {
case nil:
@ -62,7 +59,7 @@ func (dec *jsonDecoder) convertToYamlNode(data *orderedMap) (*yaml.Node, error)
}
}
var yamlMap = &yaml.Node{Kind: yaml.MappingNode, Tag: "!!map"}
var yamlMap = &CandidateNode{Kind: MappingNode, Tag: "!!map"}
for _, keyValuePair := range data.kv {
yamlValue, err := dec.convertToYamlNode(&keyValuePair.V)
if err != nil {
@ -74,9 +71,9 @@ func (dec *jsonDecoder) convertToYamlNode(data *orderedMap) (*yaml.Node, error)
}
func (dec *jsonDecoder) parseArray(dataArray []*orderedMap) (*yaml.Node, error) {
func (dec *jsonDecoder) parseArray(dataArray []*orderedMap) (*CandidateNode, error) {
var yamlMap = &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
var yamlMap = &CandidateNode{Kind: SequenceNode, Tag: "!!seq"}
for _, value := range dataArray {
yamlValue, err := dec.convertToYamlNode(value)

View File

@ -4,8 +4,6 @@ import (
"bytes"
"io"
"net/url"
yaml "gopkg.in/yaml.v3"
)
type uriDecoder struct {
@ -50,11 +48,5 @@ func (dec *uriDecoder) Decode() (*CandidateNode, error) {
return nil, err
}
dec.readAnything = true
return &CandidateNode{
Node: &yaml.Node{
Kind: yaml.ScalarNode,
Tag: "!!str",
Value: newValue,
},
}, nil
return createStringScalarNode(newValue), nil
}

View File

@ -28,12 +28,12 @@ func (e *csvEncoder) PrintLeadingContent(writer io.Writer, content string) error
return nil
}
func (e *csvEncoder) encodeRow(csvWriter *csv.Writer, contents []*yaml.Node) error {
func (e *csvEncoder) encodeRow(csvWriter *csv.Writer, contents []*CandidateNode) error {
stringValues := make([]string, len(contents))
for i, child := range contents {
if child.Kind != yaml.ScalarNode {
if child.Kind != ScalarNode {
return fmt.Errorf("csv encoding only works for arrays of scalars (string/numbers/booleans), child[%v] is a %v", i, child.Tag)
}
stringValues[i] = child.Value
@ -41,10 +41,10 @@ func (e *csvEncoder) encodeRow(csvWriter *csv.Writer, contents []*yaml.Node) err
return csvWriter.Write(stringValues)
}
func (e *csvEncoder) encodeArrays(csvWriter *csv.Writer, content []*yaml.Node) error {
func (e *csvEncoder) encodeArrays(csvWriter *csv.Writer, content []*CandidateNode) error {
for i, child := range content {
if child.Kind != yaml.SequenceNode {
if child.Kind != SequenceNode {
return fmt.Errorf("csv encoding only works for arrays of scalars (string/numbers/booleans), child[%v] is a %v", i, child.Tag)
}
err := e.encodeRow(csvWriter, child.Content)
@ -55,16 +55,16 @@ func (e *csvEncoder) encodeArrays(csvWriter *csv.Writer, content []*yaml.Node) e
return nil
}
func (e *csvEncoder) extractHeader(child *yaml.Node) ([]*yaml.Node, error) {
if child.Kind != yaml.MappingNode {
func (e *csvEncoder) extractHeader(child *CandidateNode) ([]*CandidateNode, error) {
if child.Kind != MappingNode {
return nil, fmt.Errorf("csv object encoding only works for arrays of flat objects (string key => string/numbers/boolean value), child[0] is a %v", child.Tag)
}
mapKeys := getMapKeys(child)
return mapKeys.Content, nil
}
func (e *csvEncoder) createChildRow(child *yaml.Node, headers []*yaml.Node) []*yaml.Node {
childRow := make([]*yaml.Node, 0)
func (e *csvEncoder) createChildRow(child *CandidateNode, headers []*CandidateNode) []*CandidateNode {
childRow := make([]*CandidateNode, 0)
for _, header := range headers {
keyIndex := findKeyInMap(child, header)
value := createScalarNode(nil, "")
@ -77,7 +77,7 @@ func (e *csvEncoder) createChildRow(child *yaml.Node, headers []*yaml.Node) []*y
}
func (e *csvEncoder) encodeObjects(csvWriter *csv.Writer, content []*yaml.Node) error {
func (e *csvEncoder) encodeObjects(csvWriter *csv.Writer, content []*CandidateNode) error {
headers, err := e.extractHeader(content[0])
if err != nil {
return nil
@ -102,7 +102,7 @@ func (e *csvEncoder) encodeObjects(csvWriter *csv.Writer, content []*yaml.Node)
return nil
}
func (e *csvEncoder) Encode(writer io.Writer, originalNode *yaml.Node) error {
func (e *csvEncoder) Encode(writer io.Writer, originalNode *CandidateNode) error {
if originalNode.Kind == yaml.ScalarNode {
return writeString(writer, originalNode.Value+"\n")
}

View File

@ -94,6 +94,27 @@ var jsonScenarios = []formatScenario{
input: `{"cat": "meow"}`,
expected: "D0, P[], (!!map)::cat: meow\n",
},
{
skipDoc: true,
description: "Parse json: simple: key",
input: `{"cat": "meow"}`,
expression: ".cat | key",
expected: "D0, P[], (!!str)::cat\n",
},
{
skipDoc: true,
description: "Parse json: simple: parent",
input: `{"cat": "meow"}`,
expression: ".cat | parent",
expected: "D0, P[], (!!str)::cat\n",
},
{
skipDoc: true,
description: "Parse json: simple: path",
input: `{"cat": "meow"}`,
expression: ".cat | path",
expected: "D0, P[], (!!str)::cat\n",
},
{
description: "bad json",
skipDoc: true,

View File

@ -202,7 +202,7 @@ func recurseNodeArrayEqual(lhs *yaml.Node, rhs *yaml.Node) bool {
return true
}
func findInArray(array *yaml.Node, item *yaml.Node) int {
func findInArray(array *CandidateNode, item *CandidateNode) int {
for index := 0; index < len(array.Content); index = index + 1 {
if recursiveNodeEqual(array.Content[index], item) {
@ -212,7 +212,7 @@ func findInArray(array *yaml.Node, item *yaml.Node) int {
return -1
}
func findKeyInMap(dataMap *yaml.Node, item *yaml.Node) int {
func findKeyInMap(dataMap *CandidateNode, item *CandidateNode) int {
for index := 0; index < len(dataMap.Content); index = index + 2 {
if recursiveNodeEqual(dataMap.Content[index], item) {
@ -222,7 +222,7 @@ func findKeyInMap(dataMap *yaml.Node, item *yaml.Node) int {
return -1
}
func recurseNodeObjectEqual(lhs *yaml.Node, rhs *yaml.Node) bool {
func recurseNodeObjectEqual(lhs *CandidateNode, rhs *CandidateNode) bool {
if len(lhs.Content) != len(rhs.Content) {
return false
}
@ -253,7 +253,7 @@ func guessTagFromCustomType(node *yaml.Node) string {
log.Debug("guessTagFromCustomType: could not guess underlying tag type %v", errorReading)
return node.Tag
}
guessedTag := unwrapDoc(dataBucket).Tag
guessedTag := dataBucket.unwrapDocument().Tag
log.Info("im guessing the tag %v is a %v", node.Tag, guessedTag)
return guessedTag
}
@ -406,7 +406,7 @@ func createValueOperation(value interface{}, stringValue string) *Operation {
OperationType: valueOpType,
Value: value,
StringValue: stringValue,
CandidateNode: &CandidateNode{Node: node},
CandidateNode: node,
}
}
@ -443,13 +443,12 @@ func NodeToString(node *CandidateNode) string {
if !log.IsEnabledFor(logging.DEBUG) {
return ""
}
value := node.Node
if value == nil {
if node == nil {
return "-- nil --"
}
buf := new(bytes.Buffer)
encoder := yaml.NewEncoder(buf)
errorEncoding := encoder.Encode(value)
errorEncoding := encoder.Encode(node)
if errorEncoding != nil {
log.Error("Error debugging node, %v", errorEncoding.Error())
}
@ -457,10 +456,10 @@ func NodeToString(node *CandidateNode) string {
if errorClosingEncoder != nil {
log.Error("Error closing encoder: ", errorClosingEncoder.Error())
}
tag := value.Tag
if value.Kind == yaml.DocumentNode {
tag := node.Tag
if node.Kind == DocumentNode {
tag = "doc"
} else if value.Kind == yaml.AliasNode {
} else if node.Kind == AliasNode {
tag = "alias"
}
return fmt.Sprintf(`D%v, P%v, (%v)::%v`, node.Document, node.Path, tag, buf.String())

View File

@ -3,8 +3,6 @@ package yqlib
import (
"container/list"
"fmt"
"gopkg.in/yaml.v3"
)
func isKeyOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@ -30,7 +28,7 @@ func getKeyOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
candidate := el.Value.(*CandidateNode)
if candidate.Key != nil {
results.PushBack(candidate.CreateReplacement(candidate.Key))
results.PushBack(candidate.Key.Copy())
}
}
@ -44,42 +42,42 @@ func keysOperator(d *dataTreeNavigator, context Context, expressionNode *Express
var results = list.New()
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
node := unwrapDoc(candidate.Node)
var targetNode *yaml.Node
if node.Kind == yaml.MappingNode {
targetNode = getMapKeys(node)
} else if node.Kind == yaml.SequenceNode {
targetNode = getIndicies(node)
candidate := el.Value.(*CandidateNode).unwrapDocument()
var targetNode *CandidateNode
if candidate.Kind == MappingNode {
targetNode = getMapKeys(candidate)
} else if candidate.Kind == SequenceNode {
targetNode = getIndicies(candidate)
} else {
return Context{}, fmt.Errorf("Cannot get keys of %v, keys only works for maps and arrays", node.Tag)
return Context{}, fmt.Errorf("Cannot get keys of %v, keys only works for maps and arrays", candidate.Tag)
}
result := candidate.CreateReplacement(targetNode)
results.PushBack(result)
// result := candidate.CreateReplacement(targetNode)
results.PushBack(targetNode)
}
return context.ChildContext(results), nil
}
func getMapKeys(node *yaml.Node) *yaml.Node {
contents := make([]*yaml.Node, 0)
func getMapKeys(node *CandidateNode) *CandidateNode {
contents := make([]*CandidateNode, 0)
for index := 0; index < len(node.Content); index = index + 2 {
contents = append(contents, node.Content[index])
}
return &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq", Content: contents}
return &CandidateNode{Kind: SequenceNode, Tag: "!!seq", Content: contents}
}
func getIndicies(node *yaml.Node) *yaml.Node {
var contents = make([]*yaml.Node, len(node.Content))
func getIndicies(node *CandidateNode) *CandidateNode {
var contents = make([]*CandidateNode, len(node.Content))
for index := range node.Content {
contents[index] = &yaml.Node{
Kind: yaml.ScalarNode,
contents[index] = &CandidateNode{
Kind: ScalarNode,
Tag: "!!int",
Value: fmt.Sprintf("%v", index),
}
}
return &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq", Content: contents}
return &CandidateNode{Kind: SequenceNode, Tag: "!!seq", Content: contents}
}