简体   繁体   中英

Unmarshal JSON in JSON in Go

I want to unmarshal a JSON object where one field contains a JSON string into one coherent object. How do I do that in Go?

Example:

Input:

{
  "foo":1,
  "bar":"{\\"a\\":\\"Hello\\"}"
}

Go type:

type Child struct {
    A string `json:"a"`
}

type Main struct {
    Foo int   `json:"foo"`
    Bar Child `json:"bar"`
}

I guess I'd need to implement a custom UnmarshalJSON implementation on one of the types, but its twisting my head to figure out on which one and how.

I guess you want to treat this as if the JSON String were just part of the surrounding JSON object? If so, then yes, as you suggest, a custom UnmarshalJSON method on Child should accomplish this.

func (c *Child) UnmarshalJSON(p []byte) error {
    var jsonString string
    if err := json.Unmarshal(p, &jsonString); err != nil {
        return err // Means the string was invalid
    }
    type C Child // A new type that doesn't have UnmarshalJSON method
    return json.Unmarshal([]byte(jsonString), (*C)(c))
}

See it in the playground

if i were to create a custom UnmarshalJson for that data, I would create an auxiliary struct auxMain that has the same fields as the main struct but with Bar field as string. Then it unmarshals the JSON data into this auxiliary struct, extracting the Foo field and the Bar field as a string. After that, it unmarshals the Bar field as string into the Child struct, and assigns the extracted Foo field and the Child struct to the Main struct.

It's a round about way but seems to work in the playground.

func (m *Main) UnmarshalJSON(b []byte) error {
    type auxMain struct {
        Foo int    `json:"foo"`
        Bar string `json:"bar"`
    }
    var a auxMain
    if err := json.Unmarshal(b, &a); err != nil {
        return err
    }
    var child Child
    if err := json.Unmarshal([]byte(a.Bar), &child); err != nil {
        return err
    }
    m.Foo = a.Foo
    m.Bar = child
    return nil
}

try it out in the PlayGround and see: https://go.dev/play/p/wWIceUxu1tj

Don't know if this is what you are looking for.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM