forked from mirror/go-json
Add noescape API for encoder
This commit is contained in:
parent
af6922cd2d
commit
b0b330a2dd
|
@ -9,24 +9,20 @@ jobs:
|
|||
go-version: [ "1.13", "1.14", "1.15" ]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Set up Go ${{ matrix.go-version }}
|
||||
- name: setup Go ${{ matrix.go-version }}
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Test
|
||||
- name: simple test
|
||||
run: go test -v ./ -count=1
|
||||
|
||||
# - name: Test with GC
|
||||
# run: go test -v ./ -count=1
|
||||
# env:
|
||||
# GOGC: 1
|
||||
|
||||
# - name: Test with race detector
|
||||
# run: go test -v -race ./ -count=1
|
||||
- name: test with GC pressure
|
||||
run: go test -v ./ -count=1
|
||||
env:
|
||||
GOGC: 1
|
||||
- name: test with race detector
|
||||
run: go test -v -race ./ -count=1
|
||||
coverage:
|
||||
name: Coverage
|
||||
runs-on: ubuntu-latest
|
||||
|
|
|
@ -56,6 +56,15 @@ func Benchmark_Encode_SmallStruct_GoJson(b *testing.B) {
|
|||
}
|
||||
}
|
||||
|
||||
func Benchmark_Encode_SmallStruct_GoJsonNoEscape(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := gojson.MarshalNoEscape(NewSmallPayload()); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Encode_SmallStructCached_EncodingJson(b *testing.B) {
|
||||
cached := NewSmallPayload()
|
||||
b.ReportAllocs()
|
||||
|
@ -107,6 +116,16 @@ func Benchmark_Encode_SmallStructCached_GoJson(b *testing.B) {
|
|||
}
|
||||
}
|
||||
|
||||
func Benchmark_Encode_SmallStructCached_GoJsonNoEscape(b *testing.B) {
|
||||
cached := NewSmallPayload()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := gojson.MarshalNoEscape(cached); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Encode_MediumStruct_EncodingJson(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
|
@ -153,6 +172,15 @@ func Benchmark_Encode_MediumStruct_GoJson(b *testing.B) {
|
|||
}
|
||||
}
|
||||
|
||||
func Benchmark_Encode_MediumStruct_GoJsonNoEscape(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := gojson.MarshalNoEscape(NewMediumPayload()); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Encode_MediumStructCached_EncodingJson(b *testing.B) {
|
||||
cached := NewMediumPayload()
|
||||
b.ReportAllocs()
|
||||
|
@ -204,6 +232,16 @@ func Benchmark_Encode_MediumStructCached_GoJson(b *testing.B) {
|
|||
}
|
||||
}
|
||||
|
||||
func Benchmark_Encode_MediumStructCached_GoJsonNoEscape(b *testing.B) {
|
||||
cached := NewMediumPayload()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := gojson.MarshalNoEscape(cached); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Encode_LargeStruct_EncodingJson(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
|
@ -250,6 +288,15 @@ func Benchmark_Encode_LargeStruct_GoJson(b *testing.B) {
|
|||
}
|
||||
}
|
||||
|
||||
func Benchmark_Encode_LargeStruct_GoJsonNoEscape(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := gojson.MarshalNoEscape(NewLargePayload()); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Encode_LargeStructCached_EncodingJson(b *testing.B) {
|
||||
cached := NewLargePayload()
|
||||
b.ReportAllocs()
|
||||
|
@ -300,3 +347,13 @@ func Benchmark_Encode_LargeStructCached_GoJson(b *testing.B) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Encode_LargeStructCached_GoJsonNoEscape(b *testing.B) {
|
||||
cached := NewLargePayload()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := gojson.MarshalNoEscape(cached); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
12
encode.go
12
encode.go
|
@ -111,7 +111,8 @@ func (e *Encoder) EncodeWithOption(v interface{}, opts ...EncodeOption) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
buf, err := e.encode(v)
|
||||
header := (*interfaceHeader)(unsafe.Pointer(&v))
|
||||
buf, err := e.encode(header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -159,8 +160,8 @@ func (e *Encoder) reset() {
|
|||
e.unorderedMap = false
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeForMarshal(v interface{}) ([]byte, error) {
|
||||
buf, err := e.encode(v)
|
||||
func (e *Encoder) encodeForMarshal(header *interfaceHeader) ([]byte, error) {
|
||||
buf, err := e.encode(header)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -177,9 +178,9 @@ func (e *Encoder) encodeForMarshal(v interface{}) ([]byte, error) {
|
|||
return copied, nil
|
||||
}
|
||||
|
||||
func (e *Encoder) encode(v interface{}) ([]byte, error) {
|
||||
func (e *Encoder) encode(header *interfaceHeader) ([]byte, error) {
|
||||
b := e.buf[:0]
|
||||
if v == nil {
|
||||
if header.ptr == nil {
|
||||
b = encodeNull(b)
|
||||
if e.enabledIndent {
|
||||
b = encodeIndentComma(b)
|
||||
|
@ -188,7 +189,6 @@ func (e *Encoder) encode(v interface{}) ([]byte, error) {
|
|||
}
|
||||
return b, nil
|
||||
}
|
||||
header := (*interfaceHeader)(unsafe.Pointer(&v))
|
||||
typ := header.typ
|
||||
|
||||
typeptr := uintptr(unsafe.Pointer(typ))
|
||||
|
|
27
json.go
27
json.go
|
@ -4,6 +4,7 @@ import (
|
|||
"bytes"
|
||||
"errors"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Marshaler is the interface implemented by types that
|
||||
|
@ -157,6 +158,20 @@ func Marshal(v interface{}) ([]byte, error) {
|
|||
return MarshalWithOption(v)
|
||||
}
|
||||
|
||||
// MarshalNoEscape
|
||||
func MarshalNoEscape(v interface{}) ([]byte, error) {
|
||||
var b *bytes.Buffer
|
||||
enc := NewEncoder(b)
|
||||
header := (*interfaceHeader)(unsafe.Pointer(&v))
|
||||
bytes, err := enc.encodeForMarshal(header)
|
||||
if err != nil {
|
||||
enc.release()
|
||||
return nil, err
|
||||
}
|
||||
enc.release()
|
||||
return bytes, nil
|
||||
}
|
||||
|
||||
// MarshalWithOption returns the JSON encoding of v with EncodeOption.
|
||||
func MarshalWithOption(v interface{}, opts ...EncodeOption) ([]byte, error) {
|
||||
var b *bytes.Buffer
|
||||
|
@ -166,7 +181,9 @@ func MarshalWithOption(v interface{}, opts ...EncodeOption) ([]byte, error) {
|
|||
return nil, err
|
||||
}
|
||||
}
|
||||
bytes, err := enc.encodeForMarshal(v)
|
||||
header := (*interfaceHeader)(unsafe.Pointer(&v))
|
||||
enc.ptr = header.ptr
|
||||
bytes, err := enc.encodeForMarshal(header)
|
||||
if err != nil {
|
||||
enc.release()
|
||||
return nil, err
|
||||
|
@ -192,7 +209,9 @@ func MarshalIndentWithOption(v interface{}, prefix, indent string, opts ...Encod
|
|||
}
|
||||
}
|
||||
enc.SetIndent(prefix, indent)
|
||||
bytes, err := enc.encodeForMarshal(v)
|
||||
header := (*interfaceHeader)(unsafe.Pointer(&v))
|
||||
enc.ptr = header.ptr
|
||||
bytes, err := enc.encodeForMarshal(header)
|
||||
if err != nil {
|
||||
enc.release()
|
||||
return nil, err
|
||||
|
@ -393,7 +412,9 @@ func HTMLEscape(dst *bytes.Buffer, src []byte) {
|
|||
}
|
||||
enc := NewEncoder(dst)
|
||||
enc.SetEscapeHTML(true)
|
||||
enc.buf, _ = enc.encode(v)
|
||||
header := (*interfaceHeader)(unsafe.Pointer(&v))
|
||||
enc.ptr = header.ptr
|
||||
enc.buf, _ = enc.encode(header)
|
||||
dst.Write(enc.buf[:len(enc.buf)-1]) // remove last ',' character
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue