Parsing arbitary JSON

Published: Sunday, Dec 15, 2013 Last modified: Monday, Apr 8, 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:[0].value = "New"[0].onclick = "CreateNewDoc()"[1].value = "Open"[1].onclick = "OpenDoc()"[2].value = "Close"[2].onclick = "CloseDoc()" = "File" = "file"

Python implementation

With thanks from Hyperair on Freenode’s


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)

		print(fmt.format(key=prefix, value=json.dumps(obj)))

obj = json.loads(
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 (

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)
		fmt.Printf("Unhandled: %T\n", t)

func main() {
	j, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
	var pj interface{}
	err = json.Unmarshal(j, &pj)
	if err != nil {

	dumpobj("this", pj)


Alternative example with depth:

Source is with thanks again from dsal from #go-nuts

However ideally you know the JSON structure beforehand, and you create a structure for it to map to, e.g. Only then you can access values easily like: