forked from mirror/go-json
Merge pull request #31 from goccy/feature/support-bytes
Support encoding of []byte type
This commit is contained in:
commit
4e3378926b
|
@ -171,7 +171,8 @@ func (t opType) fieldToOmitEmptyField() opType {
|
||||||
primitiveTypes := []string{
|
primitiveTypes := []string{
|
||||||
"int", "int8", "int16", "int32", "int64",
|
"int", "int8", "int16", "int32", "int64",
|
||||||
"uint", "uint8", "uint16", "uint32", "uint64",
|
"uint", "uint8", "uint16", "uint32", "uint64",
|
||||||
"float32", "float64", "bool", "string", "MarshalJSON", "MarshalText",
|
"float32", "float64", "bool", "string", "bytes",
|
||||||
|
"MarshalJSON", "MarshalText",
|
||||||
}
|
}
|
||||||
primitiveTypesUpper := []string{}
|
primitiveTypesUpper := []string{}
|
||||||
for _, typ := range primitiveTypes {
|
for _, typ := range primitiveTypes {
|
||||||
|
|
|
@ -47,6 +47,9 @@ func (e *Encoder) compile(typ *rtype, root, withIndent bool) (*opcode, error) {
|
||||||
case reflect.Ptr:
|
case reflect.Ptr:
|
||||||
return e.compilePtr(typ, root, withIndent)
|
return e.compilePtr(typ, root, withIndent)
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
|
if typ.Elem().Kind() == reflect.Uint8 {
|
||||||
|
return e.compileBytes(typ)
|
||||||
|
}
|
||||||
return e.compileSlice(typ, root, withIndent)
|
return e.compileSlice(typ, root, withIndent)
|
||||||
case reflect.Array:
|
case reflect.Array:
|
||||||
return e.compileArray(typ, root, withIndent)
|
return e.compileArray(typ, root, withIndent)
|
||||||
|
@ -163,6 +166,10 @@ func (e *Encoder) compileBool(typ *rtype) (*opcode, error) {
|
||||||
return newOpCode(opBool, typ, e.indent, newEndOp(e.indent)), nil
|
return newOpCode(opBool, typ, e.indent, newEndOp(e.indent)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) compileBytes(typ *rtype) (*opcode, error) {
|
||||||
|
return newOpCode(opBytes, typ, e.indent, newEndOp(e.indent)), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (e *Encoder) compileInterface(typ *rtype, root bool) (*opcode, error) {
|
func (e *Encoder) compileInterface(typ *rtype, root bool) (*opcode, error) {
|
||||||
return (*opcode)(unsafe.Pointer(&interfaceCode{
|
return (*opcode)(unsafe.Pointer(&interfaceCode{
|
||||||
opcodeHeader: &opcodeHeader{
|
opcodeHeader: &opcodeHeader{
|
||||||
|
|
952
encode_optype.go
952
encode_optype.go
File diff suppressed because it is too large
Load Diff
|
@ -492,6 +492,31 @@ func Test_MarshalIndent(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// byte slices are special even if they're renamed types.
|
||||||
|
type renamedByte byte
|
||||||
|
type renamedByteSlice []byte
|
||||||
|
type renamedRenamedByteSlice []renamedByte
|
||||||
|
|
||||||
|
func TestEncodeRenamedByteSlice(t *testing.T) {
|
||||||
|
s := renamedByteSlice("abc")
|
||||||
|
result, err := json.Marshal(s)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
expect := `"YWJj"`
|
||||||
|
if string(result) != expect {
|
||||||
|
t.Errorf(" got %s want %s", result, expect)
|
||||||
|
}
|
||||||
|
r := renamedRenamedByteSlice("abc")
|
||||||
|
result, err = json.Marshal(r)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if string(result) != expect {
|
||||||
|
t.Errorf(" got %s want %s", result, expect)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestMarshalRawMessageValue(t *testing.T) {
|
func TestMarshalRawMessageValue(t *testing.T) {
|
||||||
type (
|
type (
|
||||||
T1 struct {
|
T1 struct {
|
||||||
|
|
207
encode_vm.go
207
encode_vm.go
|
@ -3,6 +3,7 @@ package json
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding"
|
"encoding"
|
||||||
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
@ -66,6 +67,12 @@ func (e *Encoder) run(code *opcode) error {
|
||||||
case opBool:
|
case opBool:
|
||||||
e.encodeBool(e.ptrToBool(code.ptr))
|
e.encodeBool(e.ptrToBool(code.ptr))
|
||||||
code = code.next
|
code = code.next
|
||||||
|
case opBytes:
|
||||||
|
s := base64.StdEncoding.EncodeToString(e.ptrToBytes(code.ptr))
|
||||||
|
e.encodeByte('"')
|
||||||
|
e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s)))
|
||||||
|
e.encodeByte('"')
|
||||||
|
code = code.next
|
||||||
case opInterface:
|
case opInterface:
|
||||||
ifaceCode := code.toInterfaceCode()
|
ifaceCode := code.toInterfaceCode()
|
||||||
ptr := ifaceCode.ptr
|
ptr := ifaceCode.ptr
|
||||||
|
@ -940,6 +947,42 @@ func (e *Encoder) run(code *opcode) error {
|
||||||
field.nextField.ptr = ptr
|
field.nextField.ptr = ptr
|
||||||
code = field.next
|
code = field.next
|
||||||
}
|
}
|
||||||
|
case opStructFieldPtrHeadBytes:
|
||||||
|
code.ptr = e.ptrToPtr(code.ptr)
|
||||||
|
fallthrough
|
||||||
|
case opStructFieldHeadBytes:
|
||||||
|
field := code.toStructFieldCode()
|
||||||
|
ptr := field.ptr
|
||||||
|
if ptr == 0 {
|
||||||
|
e.encodeNull()
|
||||||
|
code = field.end
|
||||||
|
} else {
|
||||||
|
e.encodeByte('{')
|
||||||
|
e.encodeBytes(field.key)
|
||||||
|
s := base64.StdEncoding.EncodeToString(e.ptrToBytes(ptr))
|
||||||
|
e.encodeByte('"')
|
||||||
|
e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s)))
|
||||||
|
e.encodeByte('"')
|
||||||
|
field.nextField.ptr = ptr
|
||||||
|
code = field.next
|
||||||
|
}
|
||||||
|
case opStructFieldPtrAnonymousHeadBytes:
|
||||||
|
code.ptr = e.ptrToPtr(code.ptr)
|
||||||
|
fallthrough
|
||||||
|
case opStructFieldAnonymousHeadBytes:
|
||||||
|
field := code.toStructFieldCode()
|
||||||
|
ptr := field.ptr
|
||||||
|
if ptr == 0 {
|
||||||
|
code = field.end
|
||||||
|
} else {
|
||||||
|
e.encodeBytes(field.key)
|
||||||
|
s := base64.StdEncoding.EncodeToString(e.ptrToBytes(code.ptr))
|
||||||
|
e.encodeByte('"')
|
||||||
|
e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s)))
|
||||||
|
e.encodeByte('"')
|
||||||
|
field.nextField.ptr = ptr
|
||||||
|
code = field.next
|
||||||
|
}
|
||||||
case opStructFieldPtrHeadMarshalJSON:
|
case opStructFieldPtrHeadMarshalJSON:
|
||||||
code.ptr = e.ptrToPtr(code.ptr)
|
code.ptr = e.ptrToPtr(code.ptr)
|
||||||
fallthrough
|
fallthrough
|
||||||
|
@ -1371,6 +1414,29 @@ func (e *Encoder) run(code *opcode) error {
|
||||||
field.nextField.ptr = ptr
|
field.nextField.ptr = ptr
|
||||||
code = field.next
|
code = field.next
|
||||||
}
|
}
|
||||||
|
case opStructFieldPtrHeadBytesIndent:
|
||||||
|
code.ptr = e.ptrToPtr(code.ptr)
|
||||||
|
fallthrough
|
||||||
|
case opStructFieldHeadBytesIndent:
|
||||||
|
field := code.toStructFieldCode()
|
||||||
|
ptr := field.ptr
|
||||||
|
if ptr == 0 {
|
||||||
|
e.encodeIndent(code.indent)
|
||||||
|
e.encodeNull()
|
||||||
|
code = field.end
|
||||||
|
} else {
|
||||||
|
e.encodeIndent(code.indent)
|
||||||
|
e.encodeBytes([]byte{'{', '\n'})
|
||||||
|
e.encodeIndent(code.indent + 1)
|
||||||
|
e.encodeBytes(field.key)
|
||||||
|
e.encodeByte(' ')
|
||||||
|
s := base64.StdEncoding.EncodeToString(e.ptrToBytes(ptr))
|
||||||
|
e.encodeByte('"')
|
||||||
|
e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s)))
|
||||||
|
e.encodeByte('"')
|
||||||
|
field.nextField.ptr = ptr
|
||||||
|
code = field.next
|
||||||
|
}
|
||||||
case opStructFieldPtrHeadOmitEmpty:
|
case opStructFieldPtrHeadOmitEmpty:
|
||||||
if code.ptr != 0 {
|
if code.ptr != 0 {
|
||||||
code.ptr = e.ptrToPtr(code.ptr)
|
code.ptr = e.ptrToPtr(code.ptr)
|
||||||
|
@ -2043,7 +2109,56 @@ func (e *Encoder) run(code *opcode) error {
|
||||||
}
|
}
|
||||||
field.nextField.ptr = ptr
|
field.nextField.ptr = ptr
|
||||||
}
|
}
|
||||||
|
case opStructFieldPtrHeadOmitEmptyBytes:
|
||||||
|
if code.ptr != 0 {
|
||||||
|
code.ptr = e.ptrToPtr(code.ptr)
|
||||||
|
}
|
||||||
|
fallthrough
|
||||||
|
case opStructFieldHeadOmitEmptyBytes:
|
||||||
|
field := code.toStructFieldCode()
|
||||||
|
ptr := field.ptr
|
||||||
|
if ptr == 0 {
|
||||||
|
e.encodeNull()
|
||||||
|
code = field.end.next
|
||||||
|
} else {
|
||||||
|
e.encodeByte('{')
|
||||||
|
v := e.ptrToBytes(ptr + field.offset)
|
||||||
|
if len(v) == 0 {
|
||||||
|
code = field.nextField
|
||||||
|
} else {
|
||||||
|
e.encodeBytes(field.key)
|
||||||
|
s := base64.StdEncoding.EncodeToString(v)
|
||||||
|
e.encodeByte('"')
|
||||||
|
e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s)))
|
||||||
|
e.encodeByte('"')
|
||||||
|
code = field.next
|
||||||
|
}
|
||||||
|
field.nextField.ptr = ptr
|
||||||
|
}
|
||||||
|
case opStructFieldPtrAnonymousHeadOmitEmptyBytes:
|
||||||
|
if code.ptr != 0 {
|
||||||
|
code.ptr = e.ptrToPtr(code.ptr)
|
||||||
|
}
|
||||||
|
fallthrough
|
||||||
|
case opStructFieldAnonymousHeadOmitEmptyBytes:
|
||||||
|
field := code.toStructFieldCode()
|
||||||
|
ptr := field.ptr
|
||||||
|
if ptr == 0 {
|
||||||
|
code = field.end.next
|
||||||
|
} else {
|
||||||
|
v := e.ptrToBytes(ptr + field.offset)
|
||||||
|
if len(v) == 0 {
|
||||||
|
code = field.nextField
|
||||||
|
} else {
|
||||||
|
e.encodeBytes(field.key)
|
||||||
|
s := base64.StdEncoding.EncodeToString(v)
|
||||||
|
e.encodeByte('"')
|
||||||
|
e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s)))
|
||||||
|
e.encodeByte('"')
|
||||||
|
code = field.next
|
||||||
|
}
|
||||||
|
field.nextField.ptr = ptr
|
||||||
|
}
|
||||||
case opStructFieldPtrHeadOmitEmptyMarshalJSON:
|
case opStructFieldPtrHeadOmitEmptyMarshalJSON:
|
||||||
if code.ptr != 0 {
|
if code.ptr != 0 {
|
||||||
code.ptr = e.ptrToPtr(code.ptr)
|
code.ptr = e.ptrToPtr(code.ptr)
|
||||||
|
@ -2607,6 +2722,36 @@ func (e *Encoder) run(code *opcode) error {
|
||||||
}
|
}
|
||||||
field.nextField.ptr = field.ptr
|
field.nextField.ptr = field.ptr
|
||||||
}
|
}
|
||||||
|
case opStructFieldPtrHeadOmitEmptyBytesIndent:
|
||||||
|
if code.ptr != 0 {
|
||||||
|
code.ptr = e.ptrToPtr(code.ptr)
|
||||||
|
}
|
||||||
|
fallthrough
|
||||||
|
case opStructFieldHeadOmitEmptyBytesIndent:
|
||||||
|
field := code.toStructFieldCode()
|
||||||
|
ptr := field.ptr
|
||||||
|
if ptr == 0 {
|
||||||
|
e.encodeIndent(code.indent)
|
||||||
|
e.encodeNull()
|
||||||
|
code = field.end.next
|
||||||
|
} else {
|
||||||
|
e.encodeIndent(code.indent)
|
||||||
|
e.encodeBytes([]byte{'{', '\n'})
|
||||||
|
v := e.ptrToBytes(ptr + field.offset)
|
||||||
|
if len(v) == 0 {
|
||||||
|
code = field.nextField
|
||||||
|
} else {
|
||||||
|
e.encodeIndent(code.indent + 1)
|
||||||
|
e.encodeBytes(field.key)
|
||||||
|
e.encodeByte(' ')
|
||||||
|
s := base64.StdEncoding.EncodeToString(v)
|
||||||
|
e.encodeByte('"')
|
||||||
|
e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s)))
|
||||||
|
e.encodeByte('"')
|
||||||
|
code = field.next
|
||||||
|
}
|
||||||
|
field.nextField.ptr = field.ptr
|
||||||
|
}
|
||||||
case opStructField:
|
case opStructField:
|
||||||
if e.buf[len(e.buf)-1] != '{' {
|
if e.buf[len(e.buf)-1] != '{' {
|
||||||
e.encodeByte(',')
|
e.encodeByte(',')
|
||||||
|
@ -2749,6 +2894,18 @@ func (e *Encoder) run(code *opcode) error {
|
||||||
e.encodeBytes(c.key)
|
e.encodeBytes(c.key)
|
||||||
e.encodeBool(e.ptrToBool(c.ptr + c.offset))
|
e.encodeBool(e.ptrToBool(c.ptr + c.offset))
|
||||||
code = code.next
|
code = code.next
|
||||||
|
case opStructFieldBytes:
|
||||||
|
if e.buf[len(e.buf)-1] != '{' {
|
||||||
|
e.encodeByte(',')
|
||||||
|
}
|
||||||
|
c := code.toStructFieldCode()
|
||||||
|
c.nextField.ptr = c.ptr
|
||||||
|
e.encodeBytes(c.key)
|
||||||
|
s := base64.StdEncoding.EncodeToString(e.ptrToBytes(c.ptr + c.offset))
|
||||||
|
e.encodeByte('"')
|
||||||
|
e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s)))
|
||||||
|
e.encodeByte('"')
|
||||||
|
code = code.next
|
||||||
case opStructFieldMarshalJSON:
|
case opStructFieldMarshalJSON:
|
||||||
if e.buf[len(e.buf)-1] != '{' {
|
if e.buf[len(e.buf)-1] != '{' {
|
||||||
e.encodeByte(',')
|
e.encodeByte(',')
|
||||||
|
@ -2967,6 +3124,20 @@ func (e *Encoder) run(code *opcode) error {
|
||||||
e.encodeBool(e.ptrToBool(c.ptr + c.offset))
|
e.encodeBool(e.ptrToBool(c.ptr + c.offset))
|
||||||
code = code.next
|
code = code.next
|
||||||
c.nextField.ptr = c.ptr
|
c.nextField.ptr = c.ptr
|
||||||
|
case opStructFieldBytesIndent:
|
||||||
|
c := code.toStructFieldCode()
|
||||||
|
if e.buf[len(e.buf)-2] != '{' {
|
||||||
|
e.encodeBytes([]byte{',', '\n'})
|
||||||
|
}
|
||||||
|
e.encodeIndent(c.indent)
|
||||||
|
e.encodeBytes(c.key)
|
||||||
|
e.encodeByte(' ')
|
||||||
|
s := base64.StdEncoding.EncodeToString(e.ptrToBytes(c.ptr + c.offset))
|
||||||
|
e.encodeByte('"')
|
||||||
|
e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s)))
|
||||||
|
e.encodeByte('"')
|
||||||
|
code = code.next
|
||||||
|
c.nextField.ptr = c.ptr
|
||||||
case opStructFieldOmitEmpty:
|
case opStructFieldOmitEmpty:
|
||||||
c := code.toStructFieldCode()
|
c := code.toStructFieldCode()
|
||||||
p := c.ptr + c.offset
|
p := c.ptr + c.offset
|
||||||
|
@ -3155,7 +3326,21 @@ func (e *Encoder) run(code *opcode) error {
|
||||||
}
|
}
|
||||||
code = code.next
|
code = code.next
|
||||||
code.ptr = c.ptr
|
code.ptr = c.ptr
|
||||||
|
case opStructFieldOmitEmptyBytes:
|
||||||
|
c := code.toStructFieldCode()
|
||||||
|
v := e.ptrToBytes(c.ptr + c.offset)
|
||||||
|
if len(v) > 0 {
|
||||||
|
if e.buf[len(e.buf)-1] != '{' {
|
||||||
|
e.encodeByte(',')
|
||||||
|
}
|
||||||
|
e.encodeBytes(c.key)
|
||||||
|
s := base64.StdEncoding.EncodeToString(v)
|
||||||
|
e.encodeByte('"')
|
||||||
|
e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s)))
|
||||||
|
e.encodeByte('"')
|
||||||
|
}
|
||||||
|
code = code.next
|
||||||
|
code.ptr = c.ptr
|
||||||
case opStructFieldOmitEmptyMarshalJSON:
|
case opStructFieldOmitEmptyMarshalJSON:
|
||||||
c := code.toStructFieldCode()
|
c := code.toStructFieldCode()
|
||||||
ptr := c.ptr + c.offset
|
ptr := c.ptr + c.offset
|
||||||
|
@ -3420,6 +3605,24 @@ func (e *Encoder) run(code *opcode) error {
|
||||||
}
|
}
|
||||||
code = code.next
|
code = code.next
|
||||||
code.ptr = c.ptr
|
code.ptr = c.ptr
|
||||||
|
case opStructFieldOmitEmptyBytesIndent:
|
||||||
|
c := code.toStructFieldCode()
|
||||||
|
v := e.ptrToBytes(c.ptr + c.offset)
|
||||||
|
if len(v) > 0 {
|
||||||
|
if e.buf[len(e.buf)-2] != '{' {
|
||||||
|
e.encodeBytes([]byte{',', '\n'})
|
||||||
|
}
|
||||||
|
e.encodeIndent(c.indent)
|
||||||
|
e.encodeBytes(c.key)
|
||||||
|
e.encodeByte(' ')
|
||||||
|
s := base64.StdEncoding.EncodeToString(v)
|
||||||
|
e.encodeByte('"')
|
||||||
|
e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s)))
|
||||||
|
e.encodeByte('"')
|
||||||
|
}
|
||||||
|
code = code.next
|
||||||
|
code.ptr = c.ptr
|
||||||
|
|
||||||
case opStructEnd:
|
case opStructEnd:
|
||||||
e.encodeByte('}')
|
e.encodeByte('}')
|
||||||
code = code.next
|
code = code.next
|
||||||
|
|
Loading…
Reference in New Issue