Help with dynamic json

Hi,

I’m trying to parse out some json from another application and I’m having a hard time. I don’t know the format of the json as it comes in so I can’t use a static struct. I found some code online that partially works however it doesn’t seem to understand having an array at the highest point. I’m not sure how to fix it. Here is the code:
‘’’
package main

import (
“fmt”
“encoding/json”
)

func get(m interface{}, path …interface{}) interface{} {
for _, p := range path {
switch idx := p.(type) {
case string:
m = m.(map[string]interface{})[idx]
case int:
m = m.([]interface{})[idx]
}
}
return m
}

func main() {

input :=	`
[{
	"_id": "ansible_facts_localhost",
	"data": {
		"ansible_iscsi_iqn": "",
		"vcenter_centos": {
			"msg": "All items completed",
			"changed": false,
			"results": [
				{
				"ansible_loop_var": "item",
				"instance": {
					"hw_name": "mytst01",
					"hw_power_status": "poweredOn",
					"snapshots": [],
					"guest_question": null,
					"hw_interfaces": [
						"eth0",
						"eth1"
					],
					"hw_guest_id": null,
					"current_snapshot": null
				}
				}
			]
		}
	}
},{
	"_id": "ansible_facts_test02",
	"data": {
		"ansible_processor_count": 2,
		"gather_subset": [
			"all"
		],
		"ansible_product_version": "None",
		"ansible_service_mgr": "systemd",
		"ansible_fibre_channel_wwn": [],
		"module_setup": true,
		"ansible_memtotal_mb": 7821,
		"ansible_hostnqn": "",
		"ansible_distribution_version": "7.7",
		"ansible_real_user_id": 2750,
		"ansible_virtualization_role": "guest",
		"ansible_distribution_file_variety": "RedHat",
		"ansible_env": {
			"_": "/usr/bin/python",
			"LESSOPEN": "||/usr/bin/lesspipe.sh %s",
			"SSH_CLIENT": "10.0.0.2 36518 22",
			"LOGNAME": "ansible",
			"USER": "ansible",
			"PATH": "/usr/lib64/qt-3.3/bin:/usr/dialogic/bin:/usr/local/bin:/usr/bin:/bin:/opt/wf/bin",
			"LANG": "en_US.UTF-8",
			"SHELL": "/bin/bash",
			"XDG_SESSION_ID": "197",
			"HOME": "/home/ansible",
			"XDG_RUNTIME_DIR": "/run/user/2750",
			"SSH_CONNECTION": "10.0.0.2 36518 10.1.0.2 22",
			"SHLVL": "2",
			"PWD": "/home/ansible",
			"MAIL": "/var/mail/ansible"
		}
	}
}
]`

JSON := []byte(input)
 
fmt.Printf("%s\n", JSON)
var d map[string]interface{}
json.Unmarshal(JSON, &d)

fmt.Printf("\n\n get result: \n\n")
//test_path_key := "vcenter_centos"
//fmt.Println(get(d, "data",test_path_key,"results",0,"instance"))

fmt.Println(get(d, 1,"mydata"))

}

‘’’
right now when I run it panics at line 14, which is in the get function:

get result:

panic: interface conversion: interface {} is map[string]interface {}, not []interface {}

goroutine 1 [running]:
main.get(0x4d2f00, 0xc000056360, 0xc000075f68, 0x2, 0x2, 0x0, 0x0)
C:/Users/eloy04580.TELETECH/go/src/process_json/process_json.go:14 +0x1e1
main.main()
C:/Users/eloy04580.TELETECH/go/src/process_json/process_json.go:99 +0x21c
exit status 2

I’ve tried messing with this a few ways and can’t seem to make any progress. Any help would be appreciated.

Thanks,
Kevin

1 Like

Hey Kevin!

Here’s a link to a go playground that has your code working https://play.golang.org/p/NjHhT-WqOJm

I just changed your var d map[string]interface{} to var d []map[string]interface{} because the JSON you are using is a JSON array.

I then changed the get method’s second case in the switch statement to
m.([]map[string]interface{})[idx]

I believe this should work for you now. Let me know if you need more explanation about the changes I made.

1 Like

Hi Conner,

Thank you for the help! Ahh, I see. I spent way too long staring at that. That looks to be working properly now.

Kevin

1 Like

I have another question. I need to take this structure and flatten it out for eventual addition into a db. What I would like to do is iterate through it and build a new structure that is not nested with the current keys so I can just decide which values I want to add to my db without maneuvering around the multi-levels. Any thoughts?

Thanks,
Kevin

There are third-party packages to flatten json structs. Alternatively, anonymous structs can be your friends when dealing with nested and dynamic json structures. See this example.

Hi,

I don’t really have the option of defining a static struct for my data. I don’t know what it will contain. I know it’s nested, but won’t know how deep or what the keys are. I have a dynamic interface setup. The data for that is at the beginning of this thread. But I need to be able to reference each element in the structure on it’s own to add to a database, so just dumping the structure isn’t going to help.

Thanks,

Kevin