Home > Net >  Handling Nested Unstructured JSON in Go Lang
Handling Nested Unstructured JSON in Go Lang

Time:12-12

I'm trying to understand how can I access a particular data from an unstructured JSON data in GoLang. I've the following JSON and I'm trying to access "Foo1" under Material when Foo1 has some data unlike foo2 which is empty. When the object like Foo1 has data, I also need to read data from classifications section under the same name. For instance. as Foo1 under Material section has data, I should be already to print method key value under Material->Foo1 along with desc from classification -> Foo1.

package main

import (
    "encoding/json"
    "fmt"
)


type New struct {
    Desc string `json:"desc"`
}

func main() {
    bJson := `{ 
                "classifications": { "Foo1": { "desc": "It may be possible.", "sol": "The backups.", "ref": { "Sensitive Information": "https://www.sensitive_Information.html", "Control Sphere": "https://ww.example.org/data.html" },"Bar1": { "desc": "The target", "sol": "should be used.", "ref": { "ABC: Srgery": "https://www.orp.org/" } }}, 
               
                "Material": { "Backup file": [],"Foo1": [ { "method": "GET", "info": "It is not set", "level": 1, "parameter": "", "referer": "", "module": "diq", "curl_command": "curl \"https://example.com/\"", "wsg": [ "CONF-12", "O-Policy" ] }],"foo2": [],"Bar1": []},
         
                "anomalies": { "Server Error": [], "Resource consumption": [] }, 
                
                "additionals": { "web technology": [], "Methods": [] }, 

                "infos": { "url": "https://example.com/", "date": "Thu, 08 Dec 2022 06:52:04  0000"}}}`


    
        var parsedData = make(map[string]map[string]New)
    json.Unmarshal([]byte(bJson), &parsedData)
    fmt.Println("output of parsedData - \n", parsedData["classifications"]["Foo1"].Desc)
    
    //for _, v := range parsedData["Material"] {
    //  fmt.Println(v)
    //}
}

Expected output is if Foo1 is not empty:

Method is GET
desc is It may be possible.

CodePudding user response:

You can unmarshal it into a map[string]interface{} variable and then use a series of type assertions to get the information you want, like:

var parsedData = make(map[string]interface{})
json.Unmarshal([]byte(bJson), &parsedData)
fmt.Printf("Method is %s\n", parsedData["classifications"].
  (map[string]interface{})["Material"].
  (map[string]interface{})["Foo1"].
  ([]interface{})[0].
  (map[string]interface{})["method"].(string))

The above will output:

Method is GET

Here's the complete, runnable version of the code:

package main

import (
    "encoding/json"
    "fmt"
)

type New struct {
    Desc string `json:"desc"`
}

func main() {
    bJson := `{ 
                "classifications": { "Foo1": { "desc": "It may be possible.", "sol": "The backups.", "ref": { "Sensitive Information": "https://www.sensitive_Information.html", "Control Sphere": "https://ww.example.org/data.html" },"Bar1": { "desc": "The target", "sol": "should be used.", "ref": { "ABC: Srgery": "https://www.orp.org/" } }}, 
               
                "Material": { "Backup file": [],"Foo1": [ { "method": "GET", "info": "It is not set", "level": 1, "parameter": "", "referer": "", "module": "diq", "curl_command": "curl \"https://example.com/\"", "wsg": [ "CONF-12", "O-Policy" ] }],"foo2": [],"Bar1": []},
         
                "anomalies": { "Server Error": [], "Resource consumption": [] }, 
                
                "additionals": { "web technology": [], "Methods": [] }, 

                "infos": { "url": "https://example.com/", "date": "Thu, 08 Dec 2022 06:52:04  0000"}}}`

    var parsedData = make(map[string]interface{})
    json.Unmarshal([]byte(bJson), &parsedData)
    fmt.Printf("Method is %s\n", parsedData["classifications"].(map[string]interface{})["Material"].(map[string]interface{})["Foo1"].([]interface{})[0].(map[string]interface{})["method"].(string))
}

If I build this:

go build -o example main.go

It runs like this:

$ ./main
Method is GET

To check if a value does not exist or is an empty list:

data := parsedData["classifications"].(map[string]interface{})["Material"].(map[string]interface{})
val, ok := data["foo2"]
if !ok {
  panic("no key foo2 in map")
}

if count := len(val.([]interface{})); count == 0 {
  fmt.Printf("foo2 is empty\n")
} else {
  fmt.Printf("foo2 has %d items", count)
}
  •  Tags:  
  • go
  • Related