mirror of
https://github.com/mikefarah/yq.git
synced 2025-01-15 04:55:36 +00:00
wip
This commit is contained in:
parent
54f5c9ee2f
commit
52b364ec52
@ -7,7 +7,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
yaml "gopkg.in/yaml.v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type jsonDecoder struct {
|
type jsonDecoder struct {
|
||||||
@ -38,14 +37,12 @@ func (dec *jsonDecoder) Decode() (*CandidateNode, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &CandidateNode{
|
return &CandidateNode{
|
||||||
Node: &yaml.Node{
|
Kind: DocumentNode,
|
||||||
Kind: yaml.DocumentNode,
|
Content: []*CandidateNode{node},
|
||||||
Content: []*yaml.Node{node},
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dec *jsonDecoder) convertToYamlNode(data *orderedMap) (*yaml.Node, error) {
|
func (dec *jsonDecoder) convertToYamlNode(data *orderedMap) (*CandidateNode, error) {
|
||||||
if data.kv == nil {
|
if data.kv == nil {
|
||||||
switch rawData := data.altVal.(type) {
|
switch rawData := data.altVal.(type) {
|
||||||
case nil:
|
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 {
|
for _, keyValuePair := range data.kv {
|
||||||
yamlValue, err := dec.convertToYamlNode(&keyValuePair.V)
|
yamlValue, err := dec.convertToYamlNode(&keyValuePair.V)
|
||||||
if err != nil {
|
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 {
|
for _, value := range dataArray {
|
||||||
yamlValue, err := dec.convertToYamlNode(value)
|
yamlValue, err := dec.convertToYamlNode(value)
|
||||||
|
@ -4,8 +4,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
yaml "gopkg.in/yaml.v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type uriDecoder struct {
|
type uriDecoder struct {
|
||||||
@ -50,11 +48,5 @@ func (dec *uriDecoder) Decode() (*CandidateNode, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dec.readAnything = true
|
dec.readAnything = true
|
||||||
return &CandidateNode{
|
return createStringScalarNode(newValue), nil
|
||||||
Node: &yaml.Node{
|
|
||||||
Kind: yaml.ScalarNode,
|
|
||||||
Tag: "!!str",
|
|
||||||
Value: newValue,
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
@ -28,12 +28,12 @@ func (e *csvEncoder) PrintLeadingContent(writer io.Writer, content string) error
|
|||||||
return nil
|
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))
|
stringValues := make([]string, len(contents))
|
||||||
|
|
||||||
for i, child := range 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)
|
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
|
stringValues[i] = child.Value
|
||||||
@ -41,10 +41,10 @@ func (e *csvEncoder) encodeRow(csvWriter *csv.Writer, contents []*yaml.Node) err
|
|||||||
return csvWriter.Write(stringValues)
|
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 {
|
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)
|
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)
|
err := e.encodeRow(csvWriter, child.Content)
|
||||||
@ -55,16 +55,16 @@ func (e *csvEncoder) encodeArrays(csvWriter *csv.Writer, content []*yaml.Node) e
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *csvEncoder) extractHeader(child *yaml.Node) ([]*yaml.Node, error) {
|
func (e *csvEncoder) extractHeader(child *CandidateNode) ([]*CandidateNode, error) {
|
||||||
if child.Kind != yaml.MappingNode {
|
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)
|
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)
|
mapKeys := getMapKeys(child)
|
||||||
return mapKeys.Content, nil
|
return mapKeys.Content, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *csvEncoder) createChildRow(child *yaml.Node, headers []*yaml.Node) []*yaml.Node {
|
func (e *csvEncoder) createChildRow(child *CandidateNode, headers []*CandidateNode) []*CandidateNode {
|
||||||
childRow := make([]*yaml.Node, 0)
|
childRow := make([]*CandidateNode, 0)
|
||||||
for _, header := range headers {
|
for _, header := range headers {
|
||||||
keyIndex := findKeyInMap(child, header)
|
keyIndex := findKeyInMap(child, header)
|
||||||
value := createScalarNode(nil, "")
|
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])
|
headers, err := e.extractHeader(content[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
@ -102,7 +102,7 @@ func (e *csvEncoder) encodeObjects(csvWriter *csv.Writer, content []*yaml.Node)
|
|||||||
return nil
|
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 {
|
if originalNode.Kind == yaml.ScalarNode {
|
||||||
return writeString(writer, originalNode.Value+"\n")
|
return writeString(writer, originalNode.Value+"\n")
|
||||||
}
|
}
|
||||||
|
@ -94,6 +94,27 @@ var jsonScenarios = []formatScenario{
|
|||||||
input: `{"cat": "meow"}`,
|
input: `{"cat": "meow"}`,
|
||||||
expected: "D0, P[], (!!map)::cat: meow\n",
|
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",
|
description: "bad json",
|
||||||
skipDoc: true,
|
skipDoc: true,
|
||||||
|
@ -202,7 +202,7 @@ func recurseNodeArrayEqual(lhs *yaml.Node, rhs *yaml.Node) bool {
|
|||||||
return true
|
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 {
|
for index := 0; index < len(array.Content); index = index + 1 {
|
||||||
if recursiveNodeEqual(array.Content[index], item) {
|
if recursiveNodeEqual(array.Content[index], item) {
|
||||||
@ -212,7 +212,7 @@ func findInArray(array *yaml.Node, item *yaml.Node) int {
|
|||||||
return -1
|
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 {
|
for index := 0; index < len(dataMap.Content); index = index + 2 {
|
||||||
if recursiveNodeEqual(dataMap.Content[index], item) {
|
if recursiveNodeEqual(dataMap.Content[index], item) {
|
||||||
@ -222,7 +222,7 @@ func findKeyInMap(dataMap *yaml.Node, item *yaml.Node) int {
|
|||||||
return -1
|
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) {
|
if len(lhs.Content) != len(rhs.Content) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -253,7 +253,7 @@ func guessTagFromCustomType(node *yaml.Node) string {
|
|||||||
log.Debug("guessTagFromCustomType: could not guess underlying tag type %v", errorReading)
|
log.Debug("guessTagFromCustomType: could not guess underlying tag type %v", errorReading)
|
||||||
return node.Tag
|
return node.Tag
|
||||||
}
|
}
|
||||||
guessedTag := unwrapDoc(dataBucket).Tag
|
guessedTag := dataBucket.unwrapDocument().Tag
|
||||||
log.Info("im guessing the tag %v is a %v", node.Tag, guessedTag)
|
log.Info("im guessing the tag %v is a %v", node.Tag, guessedTag)
|
||||||
return guessedTag
|
return guessedTag
|
||||||
}
|
}
|
||||||
@ -406,7 +406,7 @@ func createValueOperation(value interface{}, stringValue string) *Operation {
|
|||||||
OperationType: valueOpType,
|
OperationType: valueOpType,
|
||||||
Value: value,
|
Value: value,
|
||||||
StringValue: stringValue,
|
StringValue: stringValue,
|
||||||
CandidateNode: &CandidateNode{Node: node},
|
CandidateNode: node,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,13 +443,12 @@ func NodeToString(node *CandidateNode) string {
|
|||||||
if !log.IsEnabledFor(logging.DEBUG) {
|
if !log.IsEnabledFor(logging.DEBUG) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
value := node.Node
|
if node == nil {
|
||||||
if value == nil {
|
|
||||||
return "-- nil --"
|
return "-- nil --"
|
||||||
}
|
}
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
encoder := yaml.NewEncoder(buf)
|
encoder := yaml.NewEncoder(buf)
|
||||||
errorEncoding := encoder.Encode(value)
|
errorEncoding := encoder.Encode(node)
|
||||||
if errorEncoding != nil {
|
if errorEncoding != nil {
|
||||||
log.Error("Error debugging node, %v", errorEncoding.Error())
|
log.Error("Error debugging node, %v", errorEncoding.Error())
|
||||||
}
|
}
|
||||||
@ -457,10 +456,10 @@ func NodeToString(node *CandidateNode) string {
|
|||||||
if errorClosingEncoder != nil {
|
if errorClosingEncoder != nil {
|
||||||
log.Error("Error closing encoder: ", errorClosingEncoder.Error())
|
log.Error("Error closing encoder: ", errorClosingEncoder.Error())
|
||||||
}
|
}
|
||||||
tag := value.Tag
|
tag := node.Tag
|
||||||
if value.Kind == yaml.DocumentNode {
|
if node.Kind == DocumentNode {
|
||||||
tag = "doc"
|
tag = "doc"
|
||||||
} else if value.Kind == yaml.AliasNode {
|
} else if node.Kind == AliasNode {
|
||||||
tag = "alias"
|
tag = "alias"
|
||||||
}
|
}
|
||||||
return fmt.Sprintf(`D%v, P%v, (%v)::%v`, node.Document, node.Path, tag, buf.String())
|
return fmt.Sprintf(`D%v, P%v, (%v)::%v`, node.Document, node.Path, tag, buf.String())
|
||||||
|
@ -3,8 +3,6 @@ package yqlib
|
|||||||
import (
|
import (
|
||||||
"container/list"
|
"container/list"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func isKeyOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
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)
|
candidate := el.Value.(*CandidateNode)
|
||||||
|
|
||||||
if candidate.Key != nil {
|
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()
|
var results = list.New()
|
||||||
|
|
||||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||||
candidate := el.Value.(*CandidateNode)
|
candidate := el.Value.(*CandidateNode).unwrapDocument()
|
||||||
node := unwrapDoc(candidate.Node)
|
|
||||||
var targetNode *yaml.Node
|
var targetNode *CandidateNode
|
||||||
if node.Kind == yaml.MappingNode {
|
if candidate.Kind == MappingNode {
|
||||||
targetNode = getMapKeys(node)
|
targetNode = getMapKeys(candidate)
|
||||||
} else if node.Kind == yaml.SequenceNode {
|
} else if candidate.Kind == SequenceNode {
|
||||||
targetNode = getIndicies(node)
|
targetNode = getIndicies(candidate)
|
||||||
} else {
|
} 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)
|
// result := candidate.CreateReplacement(targetNode)
|
||||||
results.PushBack(result)
|
results.PushBack(targetNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
return context.ChildContext(results), nil
|
return context.ChildContext(results), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getMapKeys(node *yaml.Node) *yaml.Node {
|
func getMapKeys(node *CandidateNode) *CandidateNode {
|
||||||
contents := make([]*yaml.Node, 0)
|
contents := make([]*CandidateNode, 0)
|
||||||
for index := 0; index < len(node.Content); index = index + 2 {
|
for index := 0; index < len(node.Content); index = index + 2 {
|
||||||
contents = append(contents, node.Content[index])
|
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 {
|
func getIndicies(node *CandidateNode) *CandidateNode {
|
||||||
var contents = make([]*yaml.Node, len(node.Content))
|
var contents = make([]*CandidateNode, len(node.Content))
|
||||||
|
|
||||||
for index := range node.Content {
|
for index := range node.Content {
|
||||||
contents[index] = &yaml.Node{
|
contents[index] = &CandidateNode{
|
||||||
Kind: yaml.ScalarNode,
|
Kind: ScalarNode,
|
||||||
Tag: "!!int",
|
Tag: "!!int",
|
||||||
Value: fmt.Sprintf("%v", index),
|
Value: fmt.Sprintf("%v", index),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq", Content: contents}
|
return &CandidateNode{Kind: SequenceNode, Tag: "!!seq", Content: contents}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user