Byte
Byte

Reputation: 47

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

Upvotes: 1

Views: 441

Answers (1)

larsks
larsks

Reputation: 311713

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"`
}

Upvotes: 2

Related Questions