Parsing arbitary JSON
Published: Sunday, Dec 15, 2013 Last modified: Monday, Nov 11, 2024
For example.json:
{"menu": {
"id": "file",
"value": "File",
"popup": {
"menuitem": [
{"value": "New", "onclick": "CreateNewDoc()"},
{"value": "Open", "onclick": "OpenDoc()"},
{"value": "Close", "onclick": "CloseDoc()"}
]
}
}}
Desired output:
this.menu.popup.menuitem[0].value = "New"
this.menu.popup.menuitem[0].onclick = "CreateNewDoc()"
this.menu.popup.menuitem[1].value = "Open"
this.menu.popup.menuitem[1].onclick = "OpenDoc()"
this.menu.popup.menuitem[2].value = "Close"
this.menu.popup.menuitem[2].onclick = "CloseDoc()"
this.menu.value = "File"
this.menu.id = "file"
Python implementation
With thanks from Hyperair on Freenode’s #hackerspace.sg
#!/usr/bin/python3
import json
import sys
fmt = '{key} = {value}'
def dump_obj(prefix, obj):
if isinstance(obj, dict):
for k, v in obj.items():
if prefix:
k = prefix + '.' + k
dump_obj(k, v)
elif isinstance(obj, list):
for i, v in enumerate(obj):
if prefix:
k = "{prefix}[{idx}]".format(prefix=prefix, idx=i)
dump_obj(k, v)
else:
print(fmt.format(key=prefix, value=json.dumps(obj)))
obj = json.loads(sys.stdin.read())
dump_obj('this', obj)
Golang implementation
Since Golang is statically typed, the important element in the code is t := x.(type)
where they type of x gets asserted, which is a required step, so you
can then iterate over the resulting structure.
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"strconv"
)
func dumpobj(prefix string, x interface{}) {
switch t := x.(type) {
case map[string]interface{}:
for k, v := range t {
dumpobj(prefix+"."+k, v)
}
case []interface{}:
for i, v := range t {
dumpobj(prefix+"["+strconv.Itoa(i)+"]", v)
}
case string:
fmt.Printf("%s = %q\n", prefix, t)
default:
fmt.Printf("Unhandled: %T\n", t)
}
}
func main() {
j, err := ioutil.ReadAll(os.Stdin)
if err != nil {
panic(err)
}
var pj interface{}
err = json.Unmarshal(j, &pj)
if err != nil {
panic(err)
}
dumpobj("this", pj)
}
Alternative example with depth: http://play.golang.org/p/QOwxJQ4z4Z
Source is with thanks again from dsal from #go-nuts http://play.golang.org/p/pt4MLJ6HcV
However ideally you know the JSON structure beforehand, and you create a structure for it to map to, e.g. http://play.golang.org/p/bdjC6DLTqo. Only then you can access values easily like:
fmt.Println(myOb.Menu.Popup.Menuitem[0].Value)