forked from mirror/go-json
WIP: add test case for MarshalJSON type
This commit is contained in:
parent
174fd57eae
commit
d3b031cef2
|
@ -281,7 +281,7 @@ func (t opType) fieldToStringTagField() opType {
|
|||
"array", "map", "mapLoad", "slice", "struct", "MarshalJSON", "MarshalText", "recursive",
|
||||
"intString", "uintString",
|
||||
"intPtr", "uintPtr", "float32Ptr", "float64Ptr", "boolPtr", "stringPtr", "bytesPtr",
|
||||
"arrayPtr", "slicePtr", "mapPtr",
|
||||
"arrayPtr", "slicePtr", "mapPtr", "marshalJSONPtr",
|
||||
"intNPtr", "uintNPtr", "float32NPtr", "float64NPtr", "boolNPtr", "stringNPtr", "bytesNPtr",
|
||||
}
|
||||
primitiveTypesUpper := []string{}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -57,9 +57,12 @@ func encodeCompileHead(ctx *encodeCompileContext) (*opcode, error) {
|
|||
typ := ctx.typ
|
||||
switch {
|
||||
case typ.Implements(marshalJSONType):
|
||||
return encodeCompileMarshalJSON(ctx)
|
||||
case rtype_ptrTo(typ).Implements(marshalJSONType):
|
||||
return encodeCompileMarshalJSONPtr(ctx)
|
||||
if typ.Kind() != reflect.Ptr || !typ.Elem().Implements(marshalJSONType) {
|
||||
fmt.Println("typ = ", typ)
|
||||
return encodeCompileMarshalJSON(ctx)
|
||||
}
|
||||
// case rtype_ptrTo(typ).Implements(marshalJSONType):
|
||||
// return encodeCompileMarshalJSONPtr(ctx)
|
||||
case typ.Implements(marshalTextType):
|
||||
return encodeCompileMarshalText(ctx)
|
||||
case rtype_ptrTo(typ).Implements(marshalTextType):
|
||||
|
@ -78,24 +81,18 @@ func encodeCompileHead(ctx *encodeCompileContext) (*opcode, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !code.indirect && isPtr {
|
||||
code.indirect = true
|
||||
}
|
||||
encodeOptimizeStructEnd(code)
|
||||
encodeLinkRecursiveCode(code)
|
||||
return code, nil
|
||||
} else if isPtr && typ.Implements(marshalTextType) {
|
||||
typ = orgType
|
||||
} else if isPtr && typ.Implements(marshalJSONType) {
|
||||
typ = orgType
|
||||
// } else if isPtr && typ.Implements(marshalJSONType) {
|
||||
// typ = orgType
|
||||
}
|
||||
code, err := encodeCompile(ctx.withType(typ), isPtr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !code.indirect && isPtr {
|
||||
code.indirect = true
|
||||
}
|
||||
encodeOptimizeStructEnd(code)
|
||||
encodeLinkRecursiveCode(code)
|
||||
return code, nil
|
||||
|
@ -171,7 +168,8 @@ func encodeOptimizeStructEnd(c *opcode) {
|
|||
if strings.Contains(prevOp, "Head") ||
|
||||
strings.Contains(prevOp, "Slice") ||
|
||||
strings.Contains(prevOp, "Array") ||
|
||||
strings.Contains(prevOp, "Map") {
|
||||
strings.Contains(prevOp, "Map") ||
|
||||
strings.Contains(prevOp, "MarshalJSON") {
|
||||
// not exists field
|
||||
code = code.next
|
||||
break
|
||||
|
@ -193,9 +191,10 @@ func encodeOptimizeStructEnd(c *opcode) {
|
|||
func encodeImplementsMarshaler(typ *rtype) bool {
|
||||
switch {
|
||||
case typ.Implements(marshalJSONType):
|
||||
fmt.Println("MarshalJSON", typ)
|
||||
return true
|
||||
case rtype_ptrTo(typ).Implements(marshalJSONType):
|
||||
return true
|
||||
// case rtype_ptrTo(typ).Implements(marshalJSONType):
|
||||
// return true
|
||||
case typ.Implements(marshalTextType):
|
||||
return true
|
||||
case rtype_ptrTo(typ).Implements(marshalTextType):
|
||||
|
@ -207,10 +206,13 @@ func encodeImplementsMarshaler(typ *rtype) bool {
|
|||
func encodeCompile(ctx *encodeCompileContext, isPtr bool) (*opcode, error) {
|
||||
typ := ctx.typ
|
||||
switch {
|
||||
case typ.Implements(marshalJSONType):
|
||||
return encodeCompileMarshalJSON(ctx)
|
||||
case rtype_ptrTo(typ).Implements(marshalJSONType):
|
||||
case isPtr && typ.Kind() == reflect.Ptr && typ.Implements(marshalJSONType) && !typ.Elem().Implements(marshalJSONType):
|
||||
// *struct{ field *implementedMarshalJSONType }
|
||||
return encodeCompileMarshalJSONPtr(ctx)
|
||||
case typ.Implements(marshalJSONType) && (typ.Kind() != reflect.Ptr || !typ.Elem().Implements(marshalJSONType)):
|
||||
return encodeCompileMarshalJSON(ctx)
|
||||
// case rtype_ptrTo(typ).Implements(marshalJSONType):
|
||||
// return encodeCompileMarshalJSONPtr(ctx)
|
||||
case typ.Implements(marshalTextType):
|
||||
return encodeCompileMarshalText(ctx)
|
||||
case rtype_ptrTo(typ).Implements(marshalTextType):
|
||||
|
@ -271,6 +273,7 @@ func encodeCompileKey(ctx *encodeCompileContext) (*opcode, error) {
|
|||
typ := ctx.typ
|
||||
switch {
|
||||
case rtype_ptrTo(typ).Implements(marshalJSONType):
|
||||
fmt.Println("key MarshalJSON", typ)
|
||||
return encodeCompileMarshalJSONPtr(ctx)
|
||||
case rtype_ptrTo(typ).Implements(marshalTextType):
|
||||
return encodeCompileMarshalTextPtr(ctx)
|
||||
|
@ -330,13 +333,15 @@ func encodeCompilePtr(ctx *encodeCompileContext) (*opcode, error) {
|
|||
}
|
||||
|
||||
func encodeCompileMarshalJSON(ctx *encodeCompileContext) (*opcode, error) {
|
||||
fmt.Println("encodeCompileMarshalJSON", ctx.typ)
|
||||
code := newOpCode(ctx, opMarshalJSON)
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
||||
func encodeCompileMarshalJSONPtr(ctx *encodeCompileContext) (*opcode, error) {
|
||||
code := newOpCode(ctx.withType(rtype_ptrTo(ctx.typ)), opMarshalJSON)
|
||||
fmt.Println("encodeCompileMarshalJSONPtr")
|
||||
code := newOpCode(ctx.withType(rtype_ptrTo(ctx.typ)), opMarshalJSONPtr)
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
@ -761,6 +766,8 @@ func encodeTypeToHeaderType(ctx *encodeCompileContext, code *opcode) opType {
|
|||
return opStructFieldHeadArrayPtr
|
||||
case opMapHead:
|
||||
return opStructFieldHeadMapPtr
|
||||
case opMarshalJSON:
|
||||
return opStructFieldHeadMarshalJSONPtr
|
||||
}
|
||||
}
|
||||
case opInt:
|
||||
|
@ -787,6 +794,8 @@ func encodeTypeToHeaderType(ctx *encodeCompileContext, code *opcode) opType {
|
|||
return opStructFieldHeadStruct
|
||||
case opMarshalJSON:
|
||||
return opStructFieldHeadMarshalJSON
|
||||
case opMarshalJSONPtr:
|
||||
return opStructFieldHeadMarshalJSONPtr
|
||||
case opMarshalText:
|
||||
return opStructFieldHeadMarshalText
|
||||
}
|
||||
|
@ -850,6 +859,8 @@ func encodeTypeToFieldType(ctx *encodeCompileContext, code *opcode) opType {
|
|||
return opStructFieldArrayPtr
|
||||
case opMapHead:
|
||||
return opStructFieldMapPtr
|
||||
case opMarshalJSON:
|
||||
return opStructFieldMarshalJSONPtr
|
||||
}
|
||||
}
|
||||
case opInt:
|
||||
|
@ -876,6 +887,8 @@ func encodeTypeToFieldType(ctx *encodeCompileContext, code *opcode) opType {
|
|||
return opStructFieldStruct
|
||||
case opMarshalJSON:
|
||||
return opStructFieldMarshalJSON
|
||||
case opMarshalJSONPtr:
|
||||
return opStructFieldMarshalJSONPtr
|
||||
case opMarshalText:
|
||||
return opStructFieldMarshalText
|
||||
}
|
||||
|
@ -956,6 +969,12 @@ func encodeStructHeader(ctx *encodeCompileContext, fieldCode *opcode, valueCode
|
|||
opStructFieldHeadStringTagMapPtr:
|
||||
*valueCode = *valueCode.next
|
||||
return valueCode.beforeLastCode()
|
||||
case opStructFieldHeadMarshalJSONPtr,
|
||||
opStructFieldHeadOmitEmptyMarshalJSONPtr,
|
||||
opStructFieldHeadStringTagMarshalJSONPtr:
|
||||
ctx.decOpcodeIndex()
|
||||
fieldCode.typ = fieldCode.typ.Elem()
|
||||
return (*opcode)(unsafe.Pointer(fieldCode))
|
||||
}
|
||||
ctx.decOpcodeIndex()
|
||||
return (*opcode)(unsafe.Pointer(fieldCode))
|
||||
|
@ -1230,21 +1249,38 @@ func encodeCompileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, error)
|
|||
for i, tag := range tags {
|
||||
field := tag.field
|
||||
fieldType := type2rtype(field.Type)
|
||||
if isPtr && i == 0 {
|
||||
// head field of pointer structure at top level
|
||||
// if field type is pointer and implements MarshalJSON or MarshalText,
|
||||
// it need to operation of dereference of pointer.
|
||||
if field.Type.Kind() == reflect.Ptr &&
|
||||
(field.Type.Implements(marshalJSONType) || field.Type.Implements(marshalTextType)) {
|
||||
fieldType = rtype_ptrTo(fieldType)
|
||||
/*
|
||||
if isPtr && i == 0 {
|
||||
// head field of pointer structure at top level
|
||||
// if field type is pointer and implements MarshalJSON or MarshalText,
|
||||
// it need to operation of dereference of pointer.
|
||||
if field.Type.Kind() == reflect.Ptr &&
|
||||
(field.Type.Implements(marshalJSONType) || field.Type.Implements(marshalTextType)) {
|
||||
fieldType = rtype_ptrTo(fieldType)
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
fieldOpcodeIndex := ctx.opcodeIndex
|
||||
fieldPtrIndex := ctx.ptrIndex
|
||||
ctx.incIndex()
|
||||
valueCode, err := encodeCompile(ctx.withType(fieldType), false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var valueCode *opcode
|
||||
if i == 0 && fieldNum == 1 && isPtr && rtype_ptrTo(fieldType).Implements(marshalJSONType) && !fieldType.Implements(marshalJSONType) {
|
||||
// *struct{ field implementedMarshalJSONType } => struct { field *implementedMarshalJSONType }
|
||||
// move pointer position from head to first field
|
||||
ctx.typ = rtype_ptrTo(fieldType)
|
||||
code, err := encodeCompileMarshalJSON(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
valueCode = code
|
||||
indirect = false
|
||||
isPtr = false
|
||||
} else {
|
||||
code, err := encodeCompile(ctx.withType(fieldType), i == 0 && isPtr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
valueCode = code
|
||||
}
|
||||
|
||||
if field.Anonymous {
|
||||
|
@ -1337,5 +1373,9 @@ func encodeCompileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, error)
|
|||
|
||||
delete(ctx.structTypeToCompiledCode, typeptr)
|
||||
|
||||
if !code.indirect && isPtr {
|
||||
code.indirect = true
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
|
1846
encode_optype.go
1846
encode_optype.go
File diff suppressed because it is too large
Load Diff
259
encode_vm.go
259
encode_vm.go
|
@ -74,6 +74,7 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
|
|||
ptrOffset := uintptr(0)
|
||||
ctxptr := ctx.ptr()
|
||||
code := codeSet.code
|
||||
fmt.Println(code.dump())
|
||||
|
||||
for {
|
||||
switch code.op {
|
||||
|
@ -543,7 +544,7 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
|
|||
}
|
||||
b = append(b, '{')
|
||||
p += code.offset
|
||||
if p == 0 || *(*uintptr)(*(*unsafe.Pointer)(unsafe.Pointer(&p))) == 0 {
|
||||
if p == 0 {
|
||||
code = code.nextField
|
||||
} else {
|
||||
b = append(b, code.key...)
|
||||
|
@ -3213,7 +3214,7 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
|
|||
code = code.next
|
||||
store(ctxptr, code.idx, p)
|
||||
}
|
||||
case opStructFieldPtrHeadMarshalJSON:
|
||||
case opStructFieldPtrHeadMarshalJSON, opStructFieldPtrHeadStringTagMarshalJSON:
|
||||
p := load(ctxptr, code.idx)
|
||||
if p == 0 {
|
||||
b = encodeNull(b)
|
||||
|
@ -3223,7 +3224,7 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
|
|||
}
|
||||
store(ctxptr, code.idx, ptrToPtr(p))
|
||||
fallthrough
|
||||
case opStructFieldHeadMarshalJSON:
|
||||
case opStructFieldHeadMarshalJSON, opStructFieldHeadStringTagMarshalJSON:
|
||||
p := load(ctxptr, code.idx)
|
||||
if p == 0 && code.indirect {
|
||||
b = encodeNull(b)
|
||||
|
@ -3233,11 +3234,15 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
|
|||
}
|
||||
b = append(b, '{')
|
||||
b = append(b, code.key...)
|
||||
bb, err := encodeMarshalJSON(b, ptrToInterface(code, p+code.offset))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if p == 0 || code.indirect && code.typ.Kind() == reflect.Ptr && ptrToPtr(p) == 0 {
|
||||
b = encodeNull(b)
|
||||
} else {
|
||||
bb, err := encodeMarshalJSON(b, ptrToInterface(code, p+code.offset))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b = bb
|
||||
}
|
||||
b = bb
|
||||
b = encodeComma(b)
|
||||
code = code.next
|
||||
case opStructFieldPtrHeadOmitEmptyMarshalJSON:
|
||||
|
@ -3251,46 +3256,103 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
|
|||
store(ctxptr, code.idx, ptrToPtr(p))
|
||||
fallthrough
|
||||
case opStructFieldHeadOmitEmptyMarshalJSON:
|
||||
ptr := load(ctxptr, code.idx)
|
||||
if ptr == 0 && code.indirect {
|
||||
p := load(ctxptr, code.idx)
|
||||
if p == 0 && code.indirect {
|
||||
b = encodeNull(b)
|
||||
b = encodeComma(b)
|
||||
code = code.end.next
|
||||
break
|
||||
}
|
||||
b = append(b, '{')
|
||||
p := ptrToUnsafePtr(ptr + code.offset)
|
||||
isPtr := code.typ.Kind() == reflect.Ptr
|
||||
if p == nil || (!isPtr && *(*unsafe.Pointer)(p) == nil) {
|
||||
if p == 0 || code.indirect && code.typ.Kind() == reflect.Ptr && ptrToPtr(p) == 0 {
|
||||
code = code.nextField
|
||||
} else {
|
||||
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{typ: code.typ, ptr: p}))
|
||||
bb, err := v.(Marshaler).MarshalJSON()
|
||||
b = append(b, code.key...)
|
||||
bb, err := encodeMarshalJSON(b, ptrToInterface(code, p+code.offset))
|
||||
if err != nil {
|
||||
return nil, &MarshalerError{
|
||||
Type: rtype2type(code.typ),
|
||||
Err: err,
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if len(bb) == 0 {
|
||||
if isPtr {
|
||||
return nil, errUnexpectedEndOfJSON(
|
||||
fmt.Sprintf("error calling MarshalJSON for type %s", code.typ),
|
||||
0,
|
||||
)
|
||||
b = bb
|
||||
b = encodeComma(b)
|
||||
code = code.next
|
||||
/*
|
||||
p := ptrToUnsafePtr(p + code.offset)
|
||||
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{typ: code.typ, ptr: p}))
|
||||
bb, err := v.(Marshaler).MarshalJSON()
|
||||
if err != nil {
|
||||
return nil, &MarshalerError{
|
||||
Type: rtype2type(code.typ),
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
code = code.nextField
|
||||
} else {
|
||||
b = append(b, code.key...)
|
||||
buf := bytes.NewBuffer(b)
|
||||
//TODO: we should validate buffer with `compact`
|
||||
if err := compact(buf, bb, false); err != nil {
|
||||
return nil, err
|
||||
if len(bb) == 0 {
|
||||
if isPtr {
|
||||
return nil, errUnexpectedEndOfJSON(
|
||||
fmt.Sprintf("error calling MarshalJSON for type %s", code.typ),
|
||||
0,
|
||||
)
|
||||
}
|
||||
code = code.nextField
|
||||
} else {
|
||||
b = append(b, code.key...)
|
||||
buf := bytes.NewBuffer(b)
|
||||
//TODO: we should validate buffer with `compact`
|
||||
if err := compact(buf, bb, false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b = buf.Bytes()
|
||||
b = encodeComma(b)
|
||||
code = code.next
|
||||
}
|
||||
b = buf.Bytes()
|
||||
b = encodeComma(b)
|
||||
code = code.next
|
||||
*/
|
||||
}
|
||||
case opStructFieldHeadMarshalJSONPtr, opStructFieldHeadStringTagMarshalJSONPtr:
|
||||
p := load(ctxptr, code.idx)
|
||||
if p == 0 && code.indirect {
|
||||
b = encodeNull(b)
|
||||
b = encodeComma(b)
|
||||
code = code.end.next
|
||||
break
|
||||
}
|
||||
b = append(b, '{')
|
||||
b = append(b, code.key...)
|
||||
if code.indirect {
|
||||
p = ptrToPtr(p + code.offset)
|
||||
}
|
||||
if p == 0 {
|
||||
b = encodeNull(b)
|
||||
} else {
|
||||
bb, err := encodeMarshalJSON(b, ptrToInterface(code, p))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b = bb
|
||||
}
|
||||
b = encodeComma(b)
|
||||
code = code.next
|
||||
case opStructFieldHeadOmitEmptyMarshalJSONPtr:
|
||||
p := load(ctxptr, code.idx)
|
||||
if p == 0 && code.indirect {
|
||||
b = encodeNull(b)
|
||||
b = encodeComma(b)
|
||||
code = code.end.next
|
||||
break
|
||||
}
|
||||
if code.indirect {
|
||||
p = ptrToPtr(p + code.offset)
|
||||
}
|
||||
b = append(b, '{')
|
||||
if p == 0 {
|
||||
code = code.nextField
|
||||
} else {
|
||||
b = append(b, code.key...)
|
||||
bb, err := encodeMarshalJSON(b, ptrToInterface(code, p+code.offset))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b = bb
|
||||
b = encodeComma(b)
|
||||
code = code.next
|
||||
}
|
||||
case opStructFieldPtrAnonymousHeadMarshalJSON:
|
||||
p := load(ctxptr, code.idx)
|
||||
|
@ -3478,53 +3540,6 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
|
|||
code = code.next
|
||||
}
|
||||
}
|
||||
case opStructFieldPtrHeadStringTagMarshalJSON:
|
||||
ptr := load(ctxptr, code.idx)
|
||||
if ptr != 0 {
|
||||
store(ctxptr, code.idx, ptrToPtr(ptr))
|
||||
}
|
||||
fallthrough
|
||||
case opStructFieldHeadStringTagMarshalJSON:
|
||||
ptr := load(ctxptr, code.idx)
|
||||
if ptr == 0 {
|
||||
b = encodeNull(b)
|
||||
b = encodeComma(b)
|
||||
code = code.end.next
|
||||
} else {
|
||||
b = append(b, '{')
|
||||
ptr += code.offset
|
||||
p := ptrToUnsafePtr(ptr)
|
||||
isPtr := code.typ.Kind() == reflect.Ptr
|
||||
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{typ: code.typ, ptr: p}))
|
||||
bb, err := v.(Marshaler).MarshalJSON()
|
||||
if err != nil {
|
||||
return nil, &MarshalerError{
|
||||
Type: rtype2type(code.typ),
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
if len(bb) == 0 {
|
||||
if isPtr {
|
||||
return nil, errUnexpectedEndOfJSON(
|
||||
fmt.Sprintf("error calling MarshalJSON for type %s", code.typ),
|
||||
0,
|
||||
)
|
||||
}
|
||||
b = append(b, code.key...)
|
||||
b = append(b, '"', '"')
|
||||
b = encodeComma(b)
|
||||
code = code.nextField
|
||||
} else {
|
||||
var buf bytes.Buffer
|
||||
if err := compact(&buf, bb, false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b = append(b, code.key...)
|
||||
b = encodeNoEscapedString(b, buf.String())
|
||||
b = encodeComma(b)
|
||||
code = code.next
|
||||
}
|
||||
}
|
||||
case opStructFieldPtrAnonymousHeadStringTagMarshalJSON:
|
||||
ptr := load(ctxptr, code.idx)
|
||||
if ptr != 0 {
|
||||
|
@ -3631,7 +3646,7 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
|
|||
case opStructFieldOmitEmpty:
|
||||
ptr := load(ctxptr, code.headIdx)
|
||||
p := ptr + code.offset
|
||||
if p == 0 || **(**uintptr)(unsafe.Pointer(&p)) == 0 {
|
||||
if p == 0 {
|
||||
code = code.nextField
|
||||
} else {
|
||||
b = append(b, code.key...)
|
||||
|
@ -4074,43 +4089,63 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
|
|||
}
|
||||
b = encodeComma(b)
|
||||
code = code.next
|
||||
case opStructFieldMarshalJSON:
|
||||
ptr := load(ctxptr, code.headIdx)
|
||||
case opStructFieldMarshalJSON, opStructFieldStringTagMarshalJSON:
|
||||
p := load(ctxptr, code.headIdx)
|
||||
b = append(b, code.key...)
|
||||
p := ptr + code.offset
|
||||
v := ptrToInterface(code, p)
|
||||
bb, err := v.(Marshaler).MarshalJSON()
|
||||
if err != nil {
|
||||
return nil, errMarshaler(code, err)
|
||||
p += code.offset
|
||||
if code.typ.Kind() == reflect.Ptr && p != 0 && ptrToPtr(p) == 0 {
|
||||
b = encodeNull(b)
|
||||
} else {
|
||||
v := ptrToInterface(code, p)
|
||||
bb, err := encodeMarshalJSON(b, v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b = bb
|
||||
}
|
||||
buf := bytes.NewBuffer(b)
|
||||
//TODO: we should validate buffer with `compact`
|
||||
if err := compact(buf, bb, false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b = buf.Bytes()
|
||||
b = encodeComma(b)
|
||||
code = code.next
|
||||
case opStructFieldStringTagMarshalJSON:
|
||||
ptr := load(ctxptr, code.headIdx)
|
||||
p := ptr + code.offset
|
||||
v := ptrToInterface(code, p)
|
||||
bb, err := v.(Marshaler).MarshalJSON()
|
||||
if err != nil {
|
||||
return nil, errMarshaler(code, err)
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
if err := compact(&buf, bb, false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b = append(b, code.key...)
|
||||
b = encodeNoEscapedString(b, buf.String())
|
||||
b = encodeComma(b)
|
||||
code = code.next
|
||||
case opStructFieldOmitEmptyMarshalJSON:
|
||||
ptr := load(ctxptr, code.headIdx)
|
||||
p := ptr + code.offset
|
||||
if code.typ.Kind() == reflect.Ptr && code.typ.Elem().Implements(marshalJSONType) {
|
||||
if code.typ.Kind() == reflect.Ptr && p != 0 && ptrToPtr(p) == 0 {
|
||||
code = code.nextField
|
||||
break
|
||||
}
|
||||
v := ptrToInterface(code, p)
|
||||
if v == nil {
|
||||
code = code.nextField
|
||||
break
|
||||
}
|
||||
b = append(b, code.key...)
|
||||
bb, err := encodeMarshalJSON(b, v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b = encodeComma(bb)
|
||||
code = code.next
|
||||
case opStructFieldMarshalJSONPtr, opStructFieldStringTagMarshalJSONPtr:
|
||||
p := load(ctxptr, code.headIdx)
|
||||
b = append(b, code.key...)
|
||||
p += code.offset
|
||||
if p != 0 {
|
||||
p = ptrToPtr(p)
|
||||
}
|
||||
if p == 0 {
|
||||
b = encodeNull(b)
|
||||
} else {
|
||||
bb, err := encodeMarshalJSON(b, ptrToInterface(code, p))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b = bb
|
||||
}
|
||||
b = encodeComma(b)
|
||||
code = code.next
|
||||
case opStructFieldOmitEmptyMarshalJSONPtr:
|
||||
p := load(ctxptr, code.headIdx)
|
||||
p += code.offset
|
||||
if p != 0 {
|
||||
p = ptrToPtr(p)
|
||||
}
|
||||
v := ptrToInterface(code, p)
|
||||
|
|
Loading…
Reference in New Issue