jsongogo-structtagencoding-json-go

parse nested json using struct in go language


Unable to parse nested json into structs objects using go lang

I have a nested json string that I want to parse using struct in Go language. The json looks like this

{"action":"add","business":{"ListId":123,"ObjectTags":[{"tagCode":"csharp","tagName":"codename","tagValue":["2"],"tagType":3},{"tagCode":"goLang","tagName":"coding","tagValue":["3"],"tagType":3}]}}

I want to parse the json using GO language. The json has nested structure so I created the structs as mentioned in the below code

package main

import (
    "encoding/json"
    "fmt"
)


type ObjectTagsList struct {
    tagCode  string
    tagName  string
    tagValue []string
}

type Model struct {
    Action   string `json:"action"`
    Business struct {
        ListId     int64  `json:"ListId"`
        ObjectTags []ObjectTagsList `json:"ObjectTags"`
    } `json:"business"`
}

func main() {
    Json := `{"action":"add","business":{"ListId":123,"ObjectTags":[{"tagCode":"csharp","tagName":"codename","tagValue":["2"],"tagType":3},{"tagCode":"goLang","tagName":"coding","tagValue":["3"],"tagType":3}]}}`

    var model Model
    json.Unmarshal([]byte(Json), &model)

    fmt.Println(model.Action) // This prints correctly as "add"
        fmt.Println(model.Business.ListId) // This prints correctly as "123"


    fmt.Println(model.Business.ObjectTags) // THIS DOES NOT PRINT THE ObjectTags. Rather this prints the ObjectTags as "[{  []} {  []}]"


}

I am unable to get the value of inner nested json into the structure.

I also tried unmarshalling the inner structure again as

var object []ObjectTagsList

//This gives error as cannot convert model.Business.ObjectTags (variable of type []ObjectTagsList) to type []byte

json.Unmarshal([]byte(model.Business.ObjectTags), &object) 

//error as cannot convert model.Business.ObjectTags (variable of type []ObjectTagsList) to type []byte

fmt.Println(object)

And this gives me an error as cannot convert model.Business.ObjectTags (variable of type []ObjectTagsList) to type []byte.

How do I map this json into the struct ? I want to map this in such a way that I can use the objects like

model.Business.ObjectTags[0].tagCode //--> Should print/store "csharp"
model.Business.ObjectTags[0].tagValue[0] //--> Should print/store "2"

Please help


Solution

  • You can only marshal/unmarshal "exported" fields -- that is, fields that are accessible outside of the current package, which in Go means "fields that start with a capital letter". So if you were to modify your code to look like this:

    
    package main
    
    import (
        "encoding/json"
        "fmt"
    )
    
    type ObjectTagsList struct {
        TagCode  string
        TagName  string
        TagValue []string
    }
    
    type Model struct {
        Action   string `json:"action"`
        Business struct {
            ListId     int64            `json:"ListId"`
            ObjectTags []ObjectTagsList `json:"ObjectTags"`
        } `json:"business"`
    }
    
    func main() {
        Json := `
    {
      "action": "add",
      "business": {
        "ListId": 123,
        "ObjectTags": [
          {
            "tagCode": "csharp",
            "tagName": "codename",
            "tagValue": [
              "2"
            ],
            "tagType": 3
          },
          {
            "tagCode": "goLang",
            "tagName": "coding",
            "tagValue": [
              "3"
            ],
            "tagType": 3
          }
        ]
      }
    }
    `
    
        var model Model
        json.Unmarshal([]byte(Json), &model)
    
        fmt.Println(model.Action)
        fmt.Println(model.Business.ListId)
    
        fmt.Println(model.Business.ObjectTags)
    }
    

    You would get as output:

    add
    123
    [{csharp codename [2]} {goLang coding [3]}]
    

    Here we're taking advantage of the fact that the json module will automatically map a key named tagCode to a struct field named TagCode, but really we should be explicit:

    type ObjectTagsList struct {
        TagCode  string   `json:"tagCode"`
        TagName  string   `json:"tagName"`
        TagValue []string `json:"tagValue"`
    }