Home > Software design >  How to unmarshal escaped JSON string with UnmarshalJSON
How to unmarshal escaped JSON string with UnmarshalJSON

Time:09-13

I'm trying to unmarshal the following JSON string

token = `{
    "id": 1,
    "token": {
        "id": 2248637,
        "metadata": {
            "name": "Name #1",
            "formats": "[{\"mimeType\": \"model/gltf-binary\", \"uri\": \"uri1\", {\"mimeType\": \"image/gif\", \"uri\": \"uri2\"}]"
        }
    }`

I can unmarshal it with 2 phases like this. However, I would like to use custom unmarshalJSON but I fail. I got error

My code as follow:

type FileFormat struct {
   MIMEType string
   URI      string
}

func (format *FileFormat) UnmarshalJSON(data []byte) error {
    var aux []interface{}

    if err := json.Unmarshal(data, &aux); err != nil {
        return err
    }

    format.MIMEType = aux[0].(string)
    format.URI = aux[1].(string)

    return nil
}

type TokenMetadata struct {
    Name         string `json:"name"`
    Formats      []FileFormat `json:"formats"`
}

type Token struct {
    ID          TokenID       `json:"tokenId"`
    Metadata    TokenMetadata `json:"metadata"`
}

func main() {
    var tokenRes OwnedToken
    if err := json.Unmarshal([]byte(token), &tokenRes); err != nil {
        fmt.Println(err)
    }
}

And the error is

json: cannot unmarshal string into Go struct field TokenMetadata.token.metadata.formats of type []main.FileFormat

How can I fix this problem? Many thanks!

CodePudding user response:

The JSON array of file formats is double encoded. Declare a Go type corresponding to the array. Double decode in the UnmarshalJSON method for that type.

type FileFormats []FileFormat

func (ff *FileFormats) UnmarshalJSON(data []byte) error {
    var s string
    if err := json.Unmarshal(data, &s); err != nil {
        return err
    }
    return json.Unmarshal(
        []byte(s),
        (*[]FileFormat)(ff))
}

type TokenMetadata struct {
    Name    string      `json:"name"`
    Formats FileFormats `json:"formats"`
}

Note: The conversion from from *FileFormats to *[]FileFormat is required to prevent recursion.

  • Related