-1

An API endpoint returns a set of posts, and a field attached_image in each post can come in as one of two types

JSON snippet:

{
   "attached_image": {   // Empty string if there is no image
      "url": "https://cataas.com/c?width=500&height=500",
      "width": 500,
      "height": 600
   },
}

Is there any way to implement it, so that if attached_image is an empty string, the field would be a string, and otherwise it would become a struct, without checking the type of the value that comes from json.Unmarshal?

frogstair
  • 444
  • 5
  • 20

1 Answers1

1

Declare a type to represent the image. Implement the json.Unmarshaler interface on the type. Handle the case where the image JSON is "" or an object in that implemention.

type Image struct {
    URL    string
    Width  int
    Height int
}

func (i *Image) UnmarshalJSON(data []byte) error {
    // Do nothing if data is the empty string.
    if bytes.Equal(data, []byte(`""`)) {
        return nil
    }

    // type imageX has same underlying struct as Image,
    // but does not have any methods. This prevents
    // json.Unmarshal from recursively calling the present
    // method.
    type imageX Image

    return json.Unmarshal(data, (*imageX)(i))
}

Use it like this:

type Result struct {
    AttachedImage *Image `json:"attached_image"`
}

var r Result
err := json.Unmarshal(data, &r)

Run it on the playground.

thwd
  • 301
  • 1
  • 6