func (d *Document) MarshalJSON() ([]byte, error) {
	type MarshalDoc Document
	doc := MarshalDoc(*d)
	switch d.Mode {
	case ObjectMode:
		var data *Object
		if len(d.Data) > 0 {
			data = d.Data[0]
		}
		type MarshalObject struct {
			MarshalDoc
			Data *Object `json:"data"`
		}
		return json.Marshal(MarshalObject{
			MarshalDoc: doc,
			Data:       data,
		})
	case ErrorMode:
		type MarshalError struct {
			MarshalDoc
			Data *Object `json:"data,omitempty"`
		}
		return json.Marshal(MarshalError{
			MarshalDoc: doc,
		})
	case ListMode:
		return json.Marshal(doc)
	default:
		return nil, ISE(fmt.Sprintf("Unexpected DocumentMode value when marshaling: %d", d.Mode))
	}
}
/*
MarshalJSON handles the custom serialization case caused by case where the "data"
element of a document might be either a single resource object, or a collection of
them.
package jsh
import (
	"encoding/json"
	"fmt"
	"net/http"
	"strings"
)
type DocumentMode int
const (
	ObjectMode DocumentMode = iota
	ListMode
	ErrorMode
)
var IncludeJSONAPIVersion = true
type JSONAPI struct {
	Version string `json:"version"`
}
type Document struct {
	Data List `json:"data"`
	Errors   ErrorList   `json:"errors,omitempty"`
	Links    *Links      `json:"links,omitempty"`
	Included []*Object   `json:"included,omitempty"`
	Meta     interface{} `json:"meta,omitempty"`
	JSONAPI  *JSONAPI    `json:"jsonapi,omitempty"`
	Status int `json:"-"`
	Mode DocumentMode `json:"-"`
	empty bool
	validated bool
}
func New() *Document {
	json := &Document{}
	if IncludeJSONAPIVersion {
		json.JSONAPI = &JSONAPI{
			Version: JSONAPIVersion,
		}
	}
	return json
}
func Build(payload Sendable) *Document {
	document := New()
	document.validated = true
	object, isObject := payload.(*Object)
	if isObject {
		document.Data = List{object}
		document.Status = object.Status
		document.Mode = ObjectMode
	}
	list, isList := payload.(List)
	if isList {
		document.Data = list
		document.Status = http.StatusOK
		document.Mode = ListMode
	}
	err, isError := payload.(*Error)
	if isError {
		document.Errors = ErrorList{err}
		document.Status = err.Status
		document.Mode = ErrorMode
	}
	errorList, isErrorList := payload.(ErrorList)
	if isErrorList {
		document.Errors = errorList
		document.Status = errorList[0].Status
		document.Mode = ErrorMode
	}
	return document
}
func (d *Document) Validate(r *http.Request, isResponse bool) *Error {
	if isResponse && d.Status < 100 || d.Status > 600 {
		return ISE("Response HTTP Status is outside of valid range")
	}
	if d.empty {
		return nil
	}
	if d.HasErrors() && d.Mode != ErrorMode {
		d.Mode = ErrorMode
	}
	switch d.Mode {
	case ErrorMode:
		if d.HasData() {
			return ISE("Attempting to respond with 'data' in an error response")
		}
	case ObjectMode:
		if d.HasData() && len(d.Data) > 1 {
			return ISE("Cannot set more than one data object in 'ObjectMode'")
		}
	case ListMode:
		if !d.HasErrors() && d.Data == nil {
			return ISE("Data cannot be nil in 'ListMode', use empty array")
		}
	}
	if !d.HasData() && d.Included != nil {
		return ISE("'included' should only be set for a response if 'data' is as well")
	}
	err := d.Data.Validate(r, isResponse)
	if err != nil {
		return err
	}
	err = d.Errors.Validate(r, isResponse)
	if err != nil {
		return err
	}
	d.validated = true
	return nil
}
func (d *Document) AddObject(object *Object) *Error {
	if d.Mode == ErrorMode {
		return ISE("Cannot add data to a document already possessing errors")
	}
	if d.Mode == ObjectMode && len(d.Data) == 1 {
		return ISE("Single 'data' object response is expected, you are attempting to add more than one element to be returned")
	}
	if d.Status == 0 {
		d.Status = object.Status
	}
	if d.Data == nil {
		d.Data = List{object}
	} else {
		d.Data = append(d.Data, object)
	}
	return nil
}
func (d *Document) AddError(newErr *Error) *Error {
	if d.HasData() {
		return ISE("Attempting to set an error, when the document has prepared response data")
	}
	if newErr.Status == 0 {
		return ISE("No HTTP Status code provided for error, cannot add to document")
	}
	if d.Status == 0 {
		d.Status = newErr.Status
	}
	if d.Errors == nil {
		d.Errors = []*Error{newErr}
	} else {
		d.Errors = append(d.Errors, newErr)
	}
	d.Mode = ErrorMode
	return nil
}
func (d *Document) First() *Object {
	if !d.HasData() {
		return nil
	}
	return d.Data[0]
}
func (d *Document) HasData() bool {
	return d.Data != nil && len(d.Data) > 0
}
func (d *Document) HasErrors() bool {
	return d.Errors != nil && len(d.Errors) > 0
}
func (d *Document) Error() string {
	errStr := "Errors:"
	for _, err := range d.Errors {
		errStr = strings.Join([]string{errStr, fmt.Sprintf("%s;", err.Error())}, "\n")
	}
	return errStr
}