Skip to content

Commit c3ff84e

Browse files
author
Derek Dowling
committed
Implementing more elegant document marshaling logic
1 parent 8f5ab8b commit c3ff84e

File tree

1 file changed

+33
-30
lines changed

1 file changed

+33
-30
lines changed

document.go

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -248,43 +248,46 @@ element of a document might be either a single resource object, or a collection
248248
them.
249249
*/
250250
func (d *Document) MarshalJSON() ([]byte, error) {
251+
// we use the MarshalDoc type to avoid recursively calling this function below
252+
// when we marshal
251253
type MarshalDoc Document
252254
doc := MarshalDoc(*d)
253255

254-
// get raw data so we can perform top level operations
255-
rawData, err := json.Marshal(doc)
256-
if err != nil {
257-
return nil, err
258-
}
259-
260-
// map back to top level JSON map for ease of use, SHITTY, I KNOW.
261-
jDoc := map[string]interface{}{}
262-
err = json.Unmarshal(rawData, &jDoc)
263-
if err != nil {
264-
return nil, ISE("Error marshaling document")
265-
}
266-
267256
switch d.Mode {
268-
case ErrorMode:
269-
delete(jDoc, "data")
270-
break
271-
272-
// here we're expected to return an object as the data value rather than an array
273-
// since it was a fetch request. Achieve this by replacing the single value array
274-
// with the object itself
275257
case ObjectMode:
276-
if d.Data == nil || len(d.Data) == 0 {
277-
jDoc["data"] = nil
278-
break
258+
var data *Object
259+
if len(d.Data) > 0 {
260+
data = d.Data[0]
279261
}
280262

281-
objects, success := jDoc["data"].([]interface{})
282-
if !success {
283-
return nil, ISE("Unable to cast data to []interface{}")
263+
// subtype that overrides regular data List with a single Object for
264+
// fetch style request/responses
265+
type MarshalObject struct {
266+
MarshalDoc
267+
Data *Object `json:"data"`
284268
}
285-
jDoc["data"] = objects[0]
286-
break
287-
}
288269

289-
return json.Marshal(jDoc)
270+
return json.Marshal(MarshalObject{
271+
MarshalDoc: doc,
272+
Data: data,
273+
})
274+
275+
case ErrorMode:
276+
// subtype that omits data as expected for error responses. We cannot simply
277+
// use json:"-" for the data attribute otherwise it will not override the
278+
// default struct tag of it the composed MarshalDoc struct.
279+
type MarshalError struct {
280+
MarshalDoc
281+
Data *Object `json:"data,omitempty"`
282+
}
283+
284+
return json.Marshal(MarshalError{
285+
MarshalDoc: doc,
286+
})
287+
288+
case ListMode:
289+
return json.Marshal(doc)
290+
default:
291+
return nil, ISE(fmt.Sprintf("Unexpected DocumentMode value when marshaling: %d", d.Mode))
292+
}
290293
}

0 commit comments

Comments
 (0)