@@ -42,6 +42,7 @@ func UnmarshalGraphQL(data []byte, v interface{}) error {
42
42
type decoder struct {
43
43
tokenizer interface {
44
44
Token () (json.Token , error )
45
+ Decode (v interface {}) error
45
46
}
46
47
47
48
// Stack of what part of input JSON we're in the middle of - objects, arrays.
@@ -68,10 +69,14 @@ func (d *decoder) Decode(v interface{}) error {
68
69
69
70
// decode decodes a single JSON value from d.tokenizer into d.vs.
70
71
func (d * decoder ) decode () error {
72
+ rawMessageValue := reflect .ValueOf (json.RawMessage {})
73
+
71
74
// The loop invariant is that the top of each d.vs stack
72
75
// is where we try to unmarshal the next JSON value we see.
73
76
for len (d .vs ) > 0 {
77
+ var tok interface {}
74
78
tok , err := d .tokenizer .Token ()
79
+
75
80
if err == io .EOF {
76
81
return errors .New ("unexpected end of JSON input" )
77
82
} else if err != nil {
@@ -87,6 +92,8 @@ func (d *decoder) decode() error {
87
92
return errors .New ("unexpected non-key in JSON input" )
88
93
}
89
94
someFieldExist := false
95
+ // If one field is raw all must be treated as raw
96
+ rawMessage := false
90
97
for i := range d .vs {
91
98
v := d .vs [i ][len (d .vs [i ])- 1 ]
92
99
if v .Kind () == reflect .Ptr {
@@ -97,6 +104,10 @@ func (d *decoder) decode() error {
97
104
f = fieldByGraphQLName (v , key )
98
105
if f .IsValid () {
99
106
someFieldExist = true
107
+ // Check for special embedded json
108
+ if f .Type () == rawMessageValue .Type () {
109
+ rawMessage = true
110
+ }
100
111
}
101
112
}
102
113
d .vs [i ] = append (d .vs [i ], f )
@@ -105,13 +116,20 @@ func (d *decoder) decode() error {
105
116
return fmt .Errorf ("struct field for %q doesn't exist in any of %v places to unmarshal" , key , len (d .vs ))
106
117
}
107
118
108
- // We've just consumed the current token, which was the key.
109
- // Read the next token, which should be the value, and let the rest of code process it.
110
- tok , err = d .tokenizer .Token ()
111
- if err == io .EOF {
112
- return errors .New ("unexpected end of JSON input" )
113
- } else if err != nil {
114
- return err
119
+ if rawMessage {
120
+ // Read the next complete object from the json stream
121
+ var data json.RawMessage
122
+ d .tokenizer .Decode (& data )
123
+ tok = data
124
+ } else {
125
+ // We've just consumed the current token, which was the key.
126
+ // Read the next token, which should be the value, and let the rest of code process it.
127
+ tok , err = d .tokenizer .Token ()
128
+ if err == io .EOF {
129
+ return errors .New ("unexpected end of JSON input" )
130
+ } else if err != nil {
131
+ return err
132
+ }
115
133
}
116
134
117
135
// Are we inside an array and seeing next value (rather than end of array)?
@@ -136,7 +154,7 @@ func (d *decoder) decode() error {
136
154
}
137
155
138
156
switch tok := tok .(type ) {
139
- case string , json.Number , bool , nil :
157
+ case string , json.Number , bool , nil , json. RawMessage :
140
158
// Value.
141
159
142
160
for i := range d .vs {
@@ -302,7 +320,7 @@ func isGraphQLFragment(f reflect.StructField) bool {
302
320
// unmarshalValue unmarshals JSON value into v.
303
321
// v must be addressable and not obtained by the use of unexported
304
322
// struct fields, otherwise unmarshalValue will panic.
305
- func unmarshalValue (value json. Token , v reflect.Value ) error {
323
+ func unmarshalValue (value interface {} , v reflect.Value ) error {
306
324
b , err := json .Marshal (value ) // TODO: Short-circuit (if profiling says it's worth it).
307
325
if err != nil {
308
326
return err
0 commit comments