Go json unmarshal options

Trying to find a simple solution for marshaling / unmashaling in the following structure

type Resource struct {
    Data []ResourceData `json:"data"`
}
type ResourceData struct {
    Id string  `json:"id"`
    Type string  `json:"type"`
    Attributes map[string]interface{} `json:"attributes"`
    Relationships map[string]Resource `json:"relationships"`
}
r := Resource{}
json.Unmarshal(body, &r)

This is great if:

body = `{"data":[{"id":"1","type":"blah"}]}`

However, I also need him to answer:

body = `{"data":{"id":"1","type":"blah"}}` //notice no slice

I could make a separate type

type ResourceSingle struct {
    Data ResourceData `json:"data"`
}

However, this would mean the need to duplicate all the functions that I tied to the resource, which is possible. However, I will need to figure out which type to cancel for it before executing it, plus when it comes to part of the relationship, each of them may contain data: [] {} or data {}, so the idea is not going to Job.

Alternatively, I could use

map[string]*json.RawMessage
//or
type Resource struct {
    Data *json.RawMessage `json:"data"`
}

but still, when in a json form, how can I find out if it is a slice or a node to provide the correct structure so that it is not marshal?

umarshal [string] .. winded.

?

, jJ

0
1

, json.Unmarshaler . json, , , .

ResourceData , :

type Resource struct {
    Data []ResourceData
}

func (r *Resource) UnmarshalJSON(b []byte) error {
    // this gives us a temporary location to unmarshal into
    m := struct {
        DataSlice struct {
            Data []ResourceData 'json:"data"'
        }
        DataStruct struct {
            Data ResourceData 'json:"data"'
        }
    }{}

    // try to unmarshal the data with a slice
    err := json.Unmarshal(b, &m.DataSlice)
    if err == nil {
        log.Println("got slice")
        r.Data = m.DataSlice.Data
        return nil
    } else if err, ok := err.(*json.UnmarshalTypeError); !ok {
        // something besides a type error occurred
        return err
    }

    // try to unmarshal the data with a struct
    err = json.Unmarshal(b, &m.DataStruct)
    if err != nil {
        return err
    }
    log.Println("got struct")

    r.Data = append(r.Data, m.DataStruct.Data)
    return nil
}

http://play.golang.org/p/YIPeYv4AfT

+2

Source: https://habr.com/ru/post/1615157/


All Articles