13 // UnmarshalJSON reads a stream and unmarshals the results in object v.
14 func UnmarshalJSON(v interface{}, stream io.Reader) error {
17 b, err := ioutil.ReadAll(stream)
26 if err := json.Unmarshal(b, &out); err != nil {
30 return unmarshalAny(reflect.ValueOf(v), out, "")
33 func unmarshalAny(value reflect.Value, data interface{}, tag reflect.StructTag) error {
35 if vtype.Kind() == reflect.Ptr {
36 vtype = vtype.Elem() // check kind of actual element type
43 // also it can't be a time object
44 if _, ok := value.Interface().(*time.Time); !ok {
48 // also it can't be a byte slice
49 if _, ok := value.Interface().([]byte); !ok {
59 if field, ok := vtype.FieldByName("_"); ok {
62 return unmarshalStruct(value, data, tag)
64 return unmarshalList(value, data, tag)
66 return unmarshalMap(value, data, tag)
68 return unmarshalScalar(value, data, tag)
72 func unmarshalStruct(value reflect.Value, data interface{}, tag reflect.StructTag) error {
76 mapData, ok := data.(map[string]interface{})
78 return fmt.Errorf("JSON value is not a structure (%#v)", data)
82 if value.Kind() == reflect.Ptr {
83 if value.IsNil() { // create the structure if it's nil
84 s := reflect.New(value.Type().Elem())
93 // unwrap any payloads
94 if payload := tag.Get("payload"); payload != "" {
95 field, _ := t.FieldByName(payload)
96 return unmarshalAny(value.FieldByName(payload), data, field.Tag)
99 for i := 0; i < t.NumField(); i++ {
101 if field.PkgPath != "" {
102 continue // ignore unexported fields
105 // figure out what this field is called
107 if locName := field.Tag.Get("locationName"); locName != "" {
111 member := value.FieldByIndex(field.Index)
112 err := unmarshalAny(member, mapData[name], field.Tag)
120 func unmarshalList(value reflect.Value, data interface{}, tag reflect.StructTag) error {
124 listData, ok := data.([]interface{})
126 return fmt.Errorf("JSON value is not a list (%#v)", data)
131 value.Set(reflect.MakeSlice(value.Type(), l, l))
134 for i, c := range listData {
135 err := unmarshalAny(value.Index(i), c, "")
144 func unmarshalMap(value reflect.Value, data interface{}, tag reflect.StructTag) error {
148 mapData, ok := data.(map[string]interface{})
150 return fmt.Errorf("JSON value is not a map (%#v)", data)
154 value.Set(reflect.MakeMap(value.Type()))
157 for k, v := range mapData {
158 kvalue := reflect.ValueOf(k)
159 vvalue := reflect.New(value.Type().Elem()).Elem()
161 unmarshalAny(vvalue, v, "")
162 value.SetMapIndex(kvalue, vvalue)
168 func unmarshalScalar(value reflect.Value, data interface{}, tag reflect.StructTag) error {
169 errf := func() error {
170 return fmt.Errorf("unsupported value: %v (%s)", value.Interface(), value.Type())
173 switch d := data.(type) {
175 return nil // nothing to do here
177 switch value.Interface().(type) {
179 value.Set(reflect.ValueOf(&d))
181 b, err := base64.StdEncoding.DecodeString(d)
185 value.Set(reflect.ValueOf(b))
190 switch value.Interface().(type) {
193 value.Set(reflect.ValueOf(&di))
195 value.Set(reflect.ValueOf(&d))
197 t := time.Unix(int64(d), 0).UTC()
198 value.Set(reflect.ValueOf(&t))
203 switch value.Interface().(type) {
205 value.Set(reflect.ValueOf(&d))
210 return fmt.Errorf("unsupported JSON value (%v)", data)