Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to accommodate for 2 different types of the same field when parsing JSON

Tags:

json

go

I'm working with a JSON rest api that can return 2 different types of the same field.

Here's an example response from the api:

"result": {
    "value": {
        "error": "Invalid data",
        "logs": [],
    }
},

But sometimes it also returns this

"result": {
    "value": {
        "error": {
             "msg": "Rate limit exceeded"
           },
        "logs": []
    }
},

As you can see the error field can change to an object.

Here's how i have defined the type in my code

type ApiResponse struct {
    Result struct {
        Value struct {
            Error string `json:"error"`
            Logs []string `json:"logs"`
        } `json:"value"`
    } `json:"result"`
}

But since the type of error can change, this sometimes causes issues when JSON unmarshaling: json: cannot unmarshal object into Go struct field .result.value.error of type string

How can i deal with this scenario?

like image 274
adm0xlan Avatar asked Oct 20 '25 01:10

adm0xlan


1 Answers

You can implement the json.Unmarshaler interface to customize how the error field will be decoded.

type ErrorMessage struct {
    Text string
}

func (e *ErrorMessage) UnmarshalJSON(data []byte) error {
    if len(data) == 0 || string(data) == "null" {
        return nil
    }
    if data[0] == '"' && data[len(data)-1] == '"' { // string?
        return json.Unmarshal(data, &e.Text)
    }
    if data[0] == '{' && data[len(data)-1] == '}' { // object?
        type T struct {
            Text string `json:"msg"`
        }
        return json.Unmarshal(data, (*T)(e))
    }
    return fmt.Errorf("unsupported error message type")
}

Then update the ApiResponse type's Error field to be of type ErrorMessage.

type ApiResponse struct {
    Result struct {
        Value struct {
            Error ErrorMessage `json:"error"`
            Logs  []string     `json:"logs"`
        } `json:"value"`
    } `json:"result"`
}

https://go.dev/play/p/U7FBiA9qB54

like image 146
mkopriva Avatar answered Oct 21 '25 15:10

mkopriva