Created
September 18, 2020 14:02
-
-
Save ethanfrogers/a8bb7a624cfd82e76f0bf2aba131b454 to your computer and use it in GitHub Desktop.
Unmarshal a list of JSON blobs into a list of structs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"encoding/json" | |
"fmt" | |
"log" | |
"reflect" | |
) | |
type MyAccount struct { | |
Name string `json:"name"` | |
Foo string `json:"foo"` | |
} | |
// UnmarshalMultiple takes multiple json documents and unmarshals them into | |
// the destination interface | |
func UnmarshalMultiple(j [][]byte, dest interface{}) error { | |
// get the value of the target interface | |
val := reflect.ValueOf(dest) | |
// only accept pointer values | |
if val.Kind() != reflect.Ptr { | |
return fmt.Errorf("destination must be a pointer") | |
} | |
elem := val.Elem() | |
if !elem.CanAddr() { | |
return fmt.Errorf("destination must be addressable (a pointer)") | |
} | |
// since we're unmarshaling multiple docs, we can only unmarshal | |
// into slice types | |
if elem.Kind() != reflect.Slice { | |
fmt.Errorf("destination must be a slice") | |
} | |
// figure out base slice type | |
// TODO: handle case where the slice base type could be a pointer value | |
baseType := elem.Type().Elem() | |
for _, b := range j { | |
newBase := reflect.New(baseType) | |
if err := json.Unmarshal(b, newBase.Interface()); err != nil { | |
return err | |
} | |
// set the value of the target to equal the value | |
elem.Set(reflect.Append(elem, newBase.Elem())) | |
} | |
return nil | |
} | |
func main() { | |
t := [][]byte{ | |
[]byte(`{"name": "thing1", "foo": "bar"}`), | |
[]byte(`{"name": "thing2", "foo": "bar2"}`), | |
} | |
var a []MyAccount | |
if err := UnmarshalMultiple(t, &a); err != nil { | |
log.Fatal(err.Error()) | |
} | |
fmt.Println(a) | |
var b []*MyAccount | |
if err := UnmarshalMultiple(t, &b); err != nil { | |
log.Fatal(err.Error()) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment