How do I turn an array of JSON objects into an array of structs with default values in Go? -
i'm working on go api can receive posts consisting of json array of objects. structure of post like:
[ { "name":"las vegas", "size":14 }, { "valid": false, "name":"buffalo", "size":63 } ]
let's have following struct:
type data { valid bool name string size float64 }
i want create bunch of data
s valid
set true
anytime it's not specified in json false
. if doing single 1 use how specify default values when parsing json in go, doing unknown number of them thing i've been able come like:
var allmap []map[string]interface{} var structs []data _, item := range allmap { var data data var v interface{} var ok bool if v, ok := item["value"]; ok { data.valid = v } else { data.valid = true } id v, ok := item["name"]; ok { data.name = v } ... structs = append(structs, data) } return structs
right struct i'm working has 14 fields, of them have values want assign defaults, others fine leave blank, of them have iterated through using approach.
is there better way?
you can use json.rawmessage
type defer unmarshaling json text value. if use type, json text stored in without unmarshaling (so can unmarshal fragment later on wish).
so in case if try unmarshal slice of such rawmessage
, can use technique linked in question, can iterate on slice of raw values (which json text each data
), create data
struct values want defaults missing values, , unmarshal slice element prepared struct. that's all.
it looks this:
alljson := []json.rawmessage{} if err := json.unmarshal(src, &alljson); err != nil { panic(err) } alldata := make([]data, len(alljson)) i, v := range alljson { // here create data default values alldata[i] = data{valid: true} if err := json.unmarshal(v, &alldata[i]); err != nil { panic(err) } }
try on go playground.
notes / variants
for efficiency (to avoid copying structs), can make alldata
slice of pointers in above example, this:
alldata := make([]*data, len(alljson)) i, v := range alljson { // here create data default values alldata[i] = &data{valid: true} if err := json.unmarshal(v, alldata[i]); err != nil { panic(err) } }
if want keep using non-pointers, efficiency can "prepare" wished default values in slice elements itself, this:
alldata := make([]data, len(alljson)) i, v := range alljson { // here set default values in slice elements // set defer 0 values: alldata[i].valid = true if err := json.unmarshal(v, &alldata[i]); err != nil { panic(err) } }
Comments
Post a Comment