Added json input functionality

This commit is contained in:
Mike Farah 2015-10-11 17:06:52 +11:00
parent 3720bf8211
commit c955815aab
4 changed files with 85 additions and 6 deletions

View File

@ -4,6 +4,19 @@ import (
"encoding/json"
)
func fromJSONBytes(jsonBytes []byte, parsedData *map[interface{}]interface{}) {
*parsedData = make(map[interface{}]interface{})
var jsonData map[string]interface{}
err := json.Unmarshal(jsonBytes, &jsonData)
if err != nil {
die("error parsing data: ", err)
}
for key, value := range jsonData {
(*parsedData)[key] = fromJSON(value)
}
}
func jsonToString(context interface{}) string {
out, err := json.Marshal(toJSON(context))
if err != nil {
@ -12,6 +25,27 @@ func jsonToString(context interface{}) string {
return string(out)
}
func fromJSON(context interface{}) interface{} {
switch context.(type) {
case []interface{}:
oldArray := context.([]interface{})
newArray := make([]interface{}, len(oldArray))
for index, value := range oldArray {
newArray[index] = fromJSON(value)
}
return newArray
case map[string]interface{}:
oldMap := context.(map[string]interface{})
newMap := make(map[interface{}]interface{})
for key, value := range oldMap {
newMap[key] = fromJSON(value)
}
return newMap
default:
return context
}
}
func toJSON(context interface{}) interface{} {
switch context.(type) {
case []interface{}:

View File

@ -1,9 +1,35 @@
package main
import (
"encoding/json"
"fmt"
"os"
"testing"
)
func TestJsonFromString(t *testing.T) {
var data = parseJSONData(`
{
"b": {
"c": 2
}
}
`)
assertResult(t, "map[b:map[c:2]]", fmt.Sprintf("%v", data))
}
func TestJsonFromString_withArray(t *testing.T) {
var data = parseJSONData(`
{
"b": [
{ "c": 5 },
{ "c": 6 }
]
}
`)
assertResult(t, "map[b:[map[c:5] map[c:6]]]", fmt.Sprintf("%v", data))
}
func TestJsonToString(t *testing.T) {
var data = parseData(`
---
@ -22,3 +48,13 @@ b:
`)
assertResult(t, "{\"b\":[{\"item\":\"one\"},{\"item\":\"two\"}]}", jsonToString(data))
}
func parseJSONData(rawData string) map[string]interface{} {
var parsedData map[string]interface{}
err := json.Unmarshal([]byte(rawData), &parsedData)
if err != nil {
fmt.Println("Error parsing json: ", err)
os.Exit(1)
}
return parsedData
}

1
sample.json Normal file
View File

@ -0,0 +1 @@
{"a":"Easy! as one two three","b":{"c":2,"d":[3,4],"e":[{"name":"fred","value":3},{"name":"sam","value":4}]}}

20
yaml.go
View File

@ -13,6 +13,7 @@ import (
var trimOutput = true
var writeInplace = false
var writeScript = ""
var inputJSON = false
var outputToJSON = false
func main() {
@ -61,6 +62,8 @@ a.b.e:
var rootCmd = &cobra.Command{Use: "yaml"}
rootCmd.PersistentFlags().BoolVarP(&trimOutput, "trim", "t", true, "trim yaml output")
rootCmd.PersistentFlags().BoolVarP(&outputToJSON, "tojson", "j", false, "output as json")
rootCmd.PersistentFlags().BoolVarP(&inputJSON, "fromjson", "J", false, "input as json")
rootCmd.AddCommand(cmdRead, cmdWrite)
rootCmd.Execute()
}
@ -72,7 +75,7 @@ func readProperty(cmd *cobra.Command, args []string) {
func read(args []string) interface{} {
var parsedData map[interface{}]interface{}
readYaml(args[0], &parsedData)
readData(args[0], &parsedData, inputJSON)
if len(args) == 1 {
return parsedData
@ -95,7 +98,7 @@ func writeProperty(cmd *cobra.Command, args []string) {
func updateYaml(args []string) interface{} {
var writeCommands map[string]interface{}
if writeScript != "" {
readYaml(writeScript, &writeCommands)
readData(writeScript, &writeCommands, false)
} else if len(args) < 3 {
die("Must provide <filename> <path_to_update> <value>")
} else {
@ -104,7 +107,7 @@ func updateYaml(args []string) interface{} {
}
var parsedData map[interface{}]interface{}
readYaml(args[0], &parsedData)
readData(args[0], &parsedData, inputJSON)
for path, value := range writeCommands {
var paths = parsePath(path)
@ -154,7 +157,7 @@ func yamlToString(context interface{}) string {
return outStr
}
func readYaml(filename string, parsedData interface{}) {
func readData(filename string, parsedData interface{}, readAsJSON bool) {
if filename == "" {
die("Must provide filename")
}
@ -166,9 +169,14 @@ func readYaml(filename string, parsedData interface{}) {
rawData = readFile(filename)
}
err := yaml.Unmarshal([]byte(rawData), parsedData)
var err interface{}
if readAsJSON {
fromJSONBytes([]byte(rawData), parsedData.(*map[interface{}]interface{}))
} else {
err = yaml.Unmarshal([]byte(rawData), parsedData)
}
if err != nil {
die("error: %v", err)
die("error parsing data: ", err)
}
}