From c955815aabcc7873520fdaec4301316ac1631f8c Mon Sep 17 00:00:00 2001 From: Mike Farah Date: Sun, 11 Oct 2015 17:06:52 +1100 Subject: [PATCH] Added json input functionality --- json_converter.go | 34 ++++++++++++++++++++++++++++++++++ json_converter_test.go | 36 ++++++++++++++++++++++++++++++++++++ sample.json | 1 + yaml.go | 20 ++++++++++++++------ 4 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 sample.json diff --git a/json_converter.go b/json_converter.go index b050a874..d9b9e1fd 100644 --- a/json_converter.go +++ b/json_converter.go @@ -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{}: diff --git a/json_converter_test.go b/json_converter_test.go index 0a1adfb2..984fd10c 100644 --- a/json_converter_test.go +++ b/json_converter_test.go @@ -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 +} diff --git a/sample.json b/sample.json new file mode 100644 index 00000000..d322c6b0 --- /dev/null +++ b/sample.json @@ -0,0 +1 @@ +{"a":"Easy! as one two three","b":{"c":2,"d":[3,4],"e":[{"name":"fred","value":3},{"name":"sam","value":4}]}} diff --git a/yaml.go b/yaml.go index f0d09056..e9d0cd75 100644 --- a/yaml.go +++ b/yaml.go @@ -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 ") } 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) } }