6 "github.com/modern-go/reflect2"
10 var marshalerType = reflect2.TypeOfPtr((*json.Marshaler)(nil)).Elem()
11 var unmarshalerType = reflect2.TypeOfPtr((*json.Unmarshaler)(nil)).Elem()
12 var textMarshalerType = reflect2.TypeOfPtr((*encoding.TextMarshaler)(nil)).Elem()
13 var textUnmarshalerType = reflect2.TypeOfPtr((*encoding.TextUnmarshaler)(nil)).Elem()
15 func createDecoderOfMarshaler(ctx *ctx, typ reflect2.Type) ValDecoder {
16 ptrType := reflect2.PtrTo(typ)
17 if ptrType.Implements(unmarshalerType) {
18 return &referenceDecoder{
19 &unmarshalerDecoder{ptrType},
22 if ptrType.Implements(textUnmarshalerType) {
23 return &referenceDecoder{
24 &textUnmarshalerDecoder{ptrType},
30 func createEncoderOfMarshaler(ctx *ctx, typ reflect2.Type) ValEncoder {
31 if typ == marshalerType {
32 checkIsEmpty := createCheckIsEmpty(ctx, typ)
33 var encoder ValEncoder = &directMarshalerEncoder{
34 checkIsEmpty: checkIsEmpty,
38 if typ.Implements(marshalerType) {
39 checkIsEmpty := createCheckIsEmpty(ctx, typ)
40 var encoder ValEncoder = &marshalerEncoder{
42 checkIsEmpty: checkIsEmpty,
46 ptrType := reflect2.PtrTo(typ)
47 if ctx.prefix != "" && ptrType.Implements(marshalerType) {
48 checkIsEmpty := createCheckIsEmpty(ctx, ptrType)
49 var encoder ValEncoder = &marshalerEncoder{
51 checkIsEmpty: checkIsEmpty,
53 return &referenceEncoder{encoder}
55 if typ == textMarshalerType {
56 checkIsEmpty := createCheckIsEmpty(ctx, typ)
57 var encoder ValEncoder = &directTextMarshalerEncoder{
58 checkIsEmpty: checkIsEmpty,
59 stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
63 if typ.Implements(textMarshalerType) {
64 checkIsEmpty := createCheckIsEmpty(ctx, typ)
65 var encoder ValEncoder = &textMarshalerEncoder{
67 stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
68 checkIsEmpty: checkIsEmpty,
72 // if prefix is empty, the type is the root type
73 if ctx.prefix != "" && ptrType.Implements(textMarshalerType) {
74 checkIsEmpty := createCheckIsEmpty(ctx, ptrType)
75 var encoder ValEncoder = &textMarshalerEncoder{
77 stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
78 checkIsEmpty: checkIsEmpty,
80 return &referenceEncoder{encoder}
85 type marshalerEncoder struct {
86 checkIsEmpty checkIsEmpty
90 func (encoder *marshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
91 obj := encoder.valType.UnsafeIndirect(ptr)
92 if encoder.valType.IsNullable() && reflect2.IsNil(obj) {
96 bytes, err := json.Marshal(obj)
104 func (encoder *marshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool {
105 return encoder.checkIsEmpty.IsEmpty(ptr)
108 type directMarshalerEncoder struct {
109 checkIsEmpty checkIsEmpty
112 func (encoder *directMarshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
113 marshaler := *(*json.Marshaler)(ptr)
114 if marshaler == nil {
118 bytes, err := marshaler.MarshalJSON()
126 func (encoder *directMarshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool {
127 return encoder.checkIsEmpty.IsEmpty(ptr)
130 type textMarshalerEncoder struct {
131 valType reflect2.Type
132 stringEncoder ValEncoder
133 checkIsEmpty checkIsEmpty
136 func (encoder *textMarshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
137 obj := encoder.valType.UnsafeIndirect(ptr)
138 if encoder.valType.IsNullable() && reflect2.IsNil(obj) {
142 marshaler := (obj).(encoding.TextMarshaler)
143 bytes, err := marshaler.MarshalText()
148 encoder.stringEncoder.Encode(unsafe.Pointer(&str), stream)
152 func (encoder *textMarshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool {
153 return encoder.checkIsEmpty.IsEmpty(ptr)
156 type directTextMarshalerEncoder struct {
157 stringEncoder ValEncoder
158 checkIsEmpty checkIsEmpty
161 func (encoder *directTextMarshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
162 marshaler := *(*encoding.TextMarshaler)(ptr)
163 if marshaler == nil {
167 bytes, err := marshaler.MarshalText()
172 encoder.stringEncoder.Encode(unsafe.Pointer(&str), stream)
176 func (encoder *directTextMarshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool {
177 return encoder.checkIsEmpty.IsEmpty(ptr)
180 type unmarshalerDecoder struct {
181 valType reflect2.Type
184 func (decoder *unmarshalerDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
185 valType := decoder.valType
186 obj := valType.UnsafeIndirect(ptr)
187 unmarshaler := obj.(json.Unmarshaler)
189 iter.unreadByte() // skip spaces
190 bytes := iter.SkipAndReturnBytes()
191 err := unmarshaler.UnmarshalJSON(bytes)
193 iter.ReportError("unmarshalerDecoder", err.Error())
197 type textUnmarshalerDecoder struct {
198 valType reflect2.Type
201 func (decoder *textUnmarshalerDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
202 valType := decoder.valType
203 obj := valType.UnsafeIndirect(ptr)
204 if reflect2.IsNil(obj) {
205 ptrType := valType.(*reflect2.UnsafePtrType)
206 elemType := ptrType.Elem()
207 elem := elemType.UnsafeNew()
208 ptrType.UnsafeSet(ptr, unsafe.Pointer(&elem))
209 obj = valType.UnsafeIndirect(ptr)
211 unmarshaler := (obj).(encoding.TextUnmarshaler)
212 str := iter.ReadString()
213 err := unmarshaler.UnmarshalText([]byte(str))
215 iter.ReportError("textUnmarshalerDecoder", err.Error())