mirror of https://github.com/goccy/go-json.git
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{
|
||||
"int", "int8", "int16", "int32", "int64",
|
||||
"uint", "uint8", "uint16", "uint32", "uint64",
|
||||
"float32", "float64", "bool", "string", "MarshalJSON", "MarshalText",
|
||||
"float32", "float64", "bool", "string", "bytes",
|
||||
"MarshalJSON", "MarshalText",
|
||||
}
|
||||
primitiveTypesUpper := []string{}
|
||||
for _, typ := range primitiveTypes {
|
||||
|
|
|
@ -47,6 +47,9 @@ func (e *Encoder) compile(typ *rtype, root, withIndent bool) (*opcode, error) {
|
|||
case reflect.Ptr:
|
||||
return e.compilePtr(typ, root, withIndent)
|
||||
case reflect.Slice:
|
||||
if typ.Elem().Kind() == reflect.Uint8 {
|
||||
return e.compileBytes(typ)
|
||||
}
|
||||
return e.compileSlice(typ, root, withIndent)
|
||||
case reflect.Array:
|
||||
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
|
||||
}
|
||||
|
||||
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) {
|
||||
return (*opcode)(unsafe.Pointer(&interfaceCode{
|
||||
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) {
|
||||
type (
|
||||
T1 struct {
|
||||
|
|
207
encode_vm.go
207
encode_vm.go
|
@ -3,6 +3,7 @@ package json
|
|||
import (
|
||||
"bytes"
|
||||
"encoding"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
|
@ -66,6 +67,12 @@ func (e *Encoder) run(code *opcode) error {
|
|||
case opBool:
|
||||
e.encodeBool(e.ptrToBool(code.ptr))
|
||||
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:
|
||||
ifaceCode := code.toInterfaceCode()
|
||||
ptr := ifaceCode.ptr
|
||||
|
@ -940,6 +947,42 @@ func (e *Encoder) run(code *opcode) error {
|
|||
field.nextField.ptr = ptr
|
||||
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:
|
||||
code.ptr = e.ptrToPtr(code.ptr)
|
||||
fallthrough
|
||||
|
@ -1371,6 +1414,29 @@ func (e *Encoder) run(code *opcode) error {
|
|||
field.nextField.ptr = ptr
|
||||
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:
|
||||
if code.ptr != 0 {
|
||||
code.ptr = e.ptrToPtr(code.ptr)
|
||||
|
@ -2043,7 +2109,56 @@ func (e *Encoder) run(code *opcode) error {
|
|||
}
|
||||
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:
|
||||
if code.ptr != 0 {
|
||||
code.ptr = e.ptrToPtr(code.ptr)
|
||||
|
@ -2607,6 +2722,36 @@ func (e *Encoder) run(code *opcode) error {
|
|||
}
|
||||
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:
|
||||
if e.buf[len(e.buf)-1] != '{' {
|
||||
e.encodeByte(',')
|
||||
|
@ -2749,6 +2894,18 @@ func (e *Encoder) run(code *opcode) error {
|
|||
e.encodeBytes(c.key)
|
||||
e.encodeBool(e.ptrToBool(c.ptr + c.offset))
|
||||
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:
|
||||
if e.buf[len(e.buf)-1] != '{' {
|
||||
e.encodeByte(',')
|
||||
|
@ -2967,6 +3124,20 @@ func (e *Encoder) run(code *opcode) error {
|
|||
e.encodeBool(e.ptrToBool(c.ptr + c.offset))
|
||||
code = code.next
|
||||
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:
|
||||
c := code.toStructFieldCode()
|
||||
p := c.ptr + c.offset
|
||||
|
@ -3155,7 +3326,21 @@ func (e *Encoder) run(code *opcode) error {
|
|||
}
|
||||
code = code.next
|
||||
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:
|
||||
c := code.toStructFieldCode()
|
||||
ptr := c.ptr + c.offset
|
||||
|
@ -3420,6 +3605,24 @@ func (e *Encoder) run(code *opcode) error {
|
|||
}
|
||||
code = code.next
|
||||
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:
|
||||
e.encodeByte('}')
|
||||
code = code.next
|
||||
|
|
Loading…
Reference in New Issue