3

I ran into some problem with unmarshalling string back to struct object when the object has a nested array of struct objects. I use the following code as a demo for my problem:

The json string is

const myStr = `{
  "name": "test_session1",
  "shared_items:": [
    {
      "id": 0,
      "name": ".aspnet"
    },
    {
      "id": 1,
      "name": ".bash_profile"
    }
  ]
}`

I have two structs as following with Session being the parent and SharedItem being the associated child(ren):

type Session struct {
    ID              uint64           `json:"id"`
    Name            string           `json:"name,omitempty"`
    SharedItems     []SharedItem `json:"shared_items"`
}

type SharedItem struct {
    ID          uint64 `json:"id"`
    Name        string `json:"name"`
}

I tried the following to unmarshal the json string, but it looks like the nested array of SharedItem objects are missing, as I saw sess object has 0 shared items, which is not what I expected.

func main() {
    var sess Session
    if err := json.Unmarshal([]byte(myStr), &sess); err != nil {
        panic(err)
    }
    fmt.Printf("sess name is: %s, and has %d shared items\n", sess.Name, len(sess.SharedItems)) // printed: sess name is test_session1, and has 0 shared items
}

Here's the link to my go playground: https://play.golang.org/p/a-y5T3tut6g

1 Answer 1

3

Golang Spec for json unmarshal describe it all

To unmarshal JSON into a struct, Unmarshal matches incoming object keys to the keys used by Marshal (either the struct field name or its tag), preferring an exact match but also accepting a case-insensitive match. By default, object keys which don't have a corresponding struct field are ignored (see Decoder.DisallowUnknownFields for an alternative).

In the json provided the json object for shared items has : colon in it as we can see it is shared_items: not shared_items which is our json tag

  "shared_items:": [
    {
      "id": 0,
      "name": ".aspnet"
    },
    {
      "id": 1,
      "name": ".bash_profile"
    }
  ]

Either remove : or append into your struct json tag to match the same.

package main

import (
    "fmt"
    "encoding/json"
)

type Session struct {
    Name            string           `json:"name,omitempty"`
    SharedItems     []SharedItem    `json:"shared_items"`
}

type SharedItem struct {
    ID          uint64 `json:"id"`
    Name        string `json:"name"`
}

const myStr = `{"name":"test_session1","shared_items":[{"id":0,"name":".aspnet"},{"id":1,"name":".bash_profile"}]}`

func main() {
    var sess Session

    if err := json.Unmarshal([]byte(myStr), &sess); err != nil {
        panic(err)
    }
    fmt.Println(sess)
    fmt.Printf("sess name is: %s, and has %d shared items\n", sess.Name, len(sess.SharedItems))
}

Playground example

Sign up to request clarification or add additional context in comments.

2 Comments

thanks, it turned to be a typo with the colon accidentally added after shared_items.
for unmarshalling json struct tags should match exactly with the json objects

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.