'How to Unmarshall data to JSON with unknown field types

I have these 'structures'

type Results struct {
    Gender string `json:"gender"`
    Name   struct {
        First string `json:"first"`
        Last  string `json:"last"`
    } `json:"name"`
    Location struct {
        Postcode int `json:"postcode"`
    }
    Registered struct {
        Date string `json:"date"`
    } `json:"registered"`
}

type Info struct {
    Seed    string `json:"seed"`
    Results int64  `json:"results"`
    Page    int64  `json:"page"`
    Version string `json:"version"`
}

type Response struct {
    Results []Results `json:"results"`
    Info    Info      `json:"info"`
}

I' making a request to an external API and converting data to a JSON view. I know in advance the types of all fields, but the problem occurs with the 'postcode' field. I'm getting different types of values, which is why I get a JSON decoding error. In this case, 'postcode' can be one of three variants:

  1. string ~ "13353"
  2. int ~ 13353
  3. string ~ "13353postcode"

Changing the postcode type from string to json.Number solved the problem. But this solution does not satisfy the third "option".

I know I can try to create a custom type and implement an interface on it. Seems to me the best solution using json.RawMessage. It’s the first I've faced this problem, So I'm still looking for an implementation of a solution to this and reading the documentation.

What's the best way solution in this case? Thanks in advance.



Solution 1:[1]

Declare a custom string type and have it implement the json.Unmarshaler interface.

For example, you could do this:

type PostCodeString string

// UnmarshalJSON implements the json.Unmarshaler interface.
func (s *PostCodeString) UnmarshalJSON(data []byte) error {
    if data[0] != '"' { // not string, so probably int, make it a string by wrapping it in double quotes
        data = []byte(`"`+string(data)+`"`)
    }

    // unmarshal as plain string
    return json.Unmarshal(data, (*string)(s))
}

https://play.golang.org/p/pp-zNNWY38M

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 mkopriva