1
0
mirror of https://github.com/json-iterator/go.git synced 2025-06-15 22:50:24 +02:00

100 Commits

Author SHA1 Message Date
8700644196 cut 0.9.18 2017-07-03 10:17:02 +08:00
6a7bf91c45 only test against 1.8 2017-07-02 19:26:06 +08:00
e417330822 fuzzy test from 1000 to 100 2017-07-02 18:18:12 +08:00
af876518e1 remove 1.6 and 1.7 2017-07-02 15:25:28 +08:00
21b9254da4 skip t.Run below 1.8 2017-07-02 15:20:18 +08:00
c009421781 fix write float compatibility 2017-07-02 15:11:36 +08:00
c4f54740f7 separate 1.8 tests 2017-07-02 14:27:16 +08:00
368bd0c1d8 fix 1.6 compatibility 2017-07-02 13:22:55 +08:00
11975d2a26 test with more go versions 2017-07-02 13:18:20 +08:00
e7404f3065 add badges 2017-07-02 13:10:00 +08:00
f60a6a17c2 test and cover multiple packages 2017-07-02 12:58:14 +08:00
2dfdcdd9db add travis.yml 2017-07-02 12:09:49 +08:00
496a8ea225 list contributors 2017-07-02 11:59:11 +08:00
ed6c434851 gofmt 2017-07-02 11:56:01 +08:00
bf002a02be #102 create correct type when pointer to Marshaler/Unmarshaler is nil 2017-07-02 11:35:30 +08:00
815aa331a8 #101 checkIsEmpty can not reuse createEncoderOfSimpleType, otherwise it will fail when struct member is not serializable 2017-07-02 11:13:21 +08:00
54ab168362 #99 support uintptr 2017-07-02 11:03:13 +08:00
87d1ea0c60 Merge pull request #100 from thockin/output_tests
Output tests for text marshal and uintptr
2017-07-02 07:41:50 +08:00
6268a1cbc8 add test for uintptr 2017-07-01 10:57:42 -07:00
d56566286c Add tests for omitempty and text methods 2017-07-01 10:28:59 -07:00
f2c50ef73b #97 omit empty behavior should follow the original type 2017-07-02 00:41:23 +08:00
d0c5988985 Merge pull request #98 from thockin/output_tests
Add tests for omitempty and json methods
2017-07-02 00:15:51 +08:00
17eed15fb5 Add tests for omitempty and json methods 2017-07-01 08:26:42 -07:00
e260979001 #95 struct and empty struct is considered as notempty 2017-07-01 11:48:17 +08:00
3cf9b7c253 Merge pull request #96 from thockin/output_tests
Add test for omitempty on struct
2017-07-01 11:33:17 +08:00
800df52ccd Add test for omitempty on struct 2017-06-30 20:32:27 -07:00
e3ba0e7b7e #93 fix omitempty within embedded struct 2017-07-01 09:27:48 +08:00
e366c72b81 Merge pull request #94 from thockin/output_tests
Add test for embedded+omitempty
2017-07-01 09:01:13 +08:00
69551ef38f Add test for embedded+omitempty 2017-06-30 15:16:42 -07:00
abcf9a8d76 fix tests 2017-07-01 00:35:19 +08:00
fa0965a968 #90 trim spaces when UnmarshalJSON 2017-07-01 00:33:42 +08:00
04eae11ba5 #91 fix one ptr embedded struct 2017-07-01 00:09:40 +08:00
ea8fa7cc63 #91 fix embedded and , 2017-07-01 00:00:38 +08:00
6540266aaf Merge pull request #92 from thockin/output_tests
Better tests for field name tags
2017-06-30 23:53:02 +08:00
ddfbb0c62e better tests for field name tags 2017-06-30 08:16:43 -07:00
a3a2d1cd25 #87 fix embedded field sorting order 2017-06-30 14:01:50 +08:00
401a56bc20 #88 #85 support embedded struct with json tags 2017-06-30 13:26:50 +08:00
cfaa11f837 Merge pull request #89 from thockin/output_tests
More output tests
2017-06-30 13:21:54 +08:00
c1411e0ad5 Add test for json tag on embedded field 2017-06-29 22:01:16 -07:00
9ec64591b6 Enhance test for overlap and embedded 2017-06-29 22:01:16 -07:00
b07d1abc4f Add output_test for partial unmarshal 2017-06-29 22:01:14 -07:00
79c4040505 sync up some straggler json_tests 2017-06-29 22:00:39 -07:00
7fa780bd5d Uncommit files accidentally added 2017-06-29 22:00:27 -07:00
7244d730b9 Merge pull request #84 from thockin/output_tests
Output tests for embedded marshalers and arrays
2017-06-29 22:51:46 +08:00
12be6e0d43 Add tests for arrays 2017-06-29 07:25:19 -07:00
3cfe590a13 Add output test for embedded marshalers 2017-06-29 07:14:33 -07:00
678c297af3 #75 support MarshalIndent 2017-06-29 20:48:27 +08:00
1253b8edd3 gofmt 2017-06-29 20:40:25 +08:00
fb382c0ec1 fix -, 2017-06-29 20:40:07 +08:00
09cb1d9236 #81 handle field name conflict properly 2017-06-29 20:34:40 +08:00
e6c24947ee array is just like struct, one element case special for interface{ 2017-06-29 18:58:40 +08:00
a6673c983a slice embedded in struct will not be optimized by interface{} 2017-06-29 18:52:03 +08:00
ec7b40d104 update ignore 2017-06-29 18:45:20 +08:00
84fa033353 #80 fix the case when embedded struct ptr is nil 2017-06-29 18:45:11 +08:00
4e608af2c7 #80 fix embedded builtins 2017-06-29 10:45:29 +08:00
3458ccdb20 Merge pull request #83 from thockin/output_tests
Methods on aliased types are not valid map keys
2017-06-29 09:43:12 +08:00
45ccfb031f Methods on aliased types are not valid map keys 2017-06-28 09:38:15 -07:00
545a32f2a1 #76 support TextUnmarshal 2017-06-29 00:14:55 +08:00
08dbc98040 #76 fix UnmarshalJSON 2017-06-28 23:55:32 +08:00
82dabdcdbf #77 support -, 2017-06-28 23:47:32 +08:00
76e62088df #78 not null pointer is considered not empty 2017-06-28 23:39:46 +08:00
faaa59222a #79 fix string tag on string field 2017-06-28 23:37:10 +08:00
91ef89a6a2 WIP: MarshalIndent 2017-06-28 23:22:05 +08:00
3e3caf9184 Merge pull request #82 from thockin/output_tests
Huge updates to output tests
2017-06-28 23:20:59 +08:00
03a2daaeee Add a test for caseless unmarshal 2017-06-28 08:11:38 -07:00
4652ac6cc2 Add output tests for embedded types 2017-06-28 08:11:38 -07:00
8a9f2b9179 Add output test for manual text marshalers 2017-06-28 08:11:33 -07:00
0db2d74de8 Add output test for manual json marshalers 2017-06-28 08:11:02 -07:00
d6ef711c18 Better errors in output_tests 2017-06-28 07:48:55 -07:00
628fedf63c Add output tests for map keys with TextMarshal 2017-06-28 07:48:55 -07:00
5bb7a1f7af Add output test for 'string' tag 2017-06-28 07:48:55 -07:00
c2c9981062 catch errors in output_tests 2017-06-28 07:48:55 -07:00
e40d614037 Add output test for json tag field names 2017-06-28 07:48:55 -07:00
1589ab2fd7 Add output tests for omitempty 2017-06-28 07:48:49 -07:00
97ee4ad4a2 Reorganize output_tests for structs
As I added more and more cases, I found the dir structure hard to
navigate.  The new structure follows how you read a type:

   e.g. struct { F *string } -> struct/ptr_string

This exposed some redundant cases and some missing cases, too.
2017-06-27 19:51:13 +01:00
f09f778ca9 Reorganize output_tests for slices
As I added more and more cases, I found the dir structure hard to
navigate.  The new structure follows how you read a type:

   e.g. []*string -> slice/ptr_string

This exposed some redundant cases and some missing cases, too.
2017-06-27 19:21:17 +01:00
9fc858b117 Reorganize output_tests for maps
As I added more and more cases, I found the dir structure hard to
navigate.  The new structure follows how you read a type:

e.g. map[string]*string -> map/string/ptr_string

This exposed some redundant cases and some missing cases, too. Now
map[string] is the "main" test case that exercises all the variants of
value types, and the other key types are just to prove that they
basically work.
2017-06-27 19:19:37 +01:00
f93d25f8b1 Add output tests for slices of slices 2017-06-27 18:28:52 +01:00
7cd7a6cc7c Add output tests for maps of maps/slices/structs 2017-06-27 11:58:07 +01:00
7d6c9374e8 Add output test for structs of struct ptrs 2017-06-27 11:46:55 +01:00
e16ee7f8ac Add output tests for structs of slices and maps 2017-06-27 11:41:17 +01:00
cf6367546b Add output tests for structs of structs 2017-06-27 11:28:17 +01:00
dc44e85a86 #73 fix interface{} optimization for one ptr field struct and array 2017-06-26 22:37:24 +08:00
85f7a1b0b3 Merge pull request #74 from thockin/output_tests
Output tests for structs
2017-06-26 21:49:06 +08:00
507a446eda Add output_tests for structs of ptrs 2017-06-26 06:09:00 -07:00
76eefc25ba Add output_test for empty structs 2017-06-26 05:45:54 -07:00
21a16bd252 Add output_tests for structs of builtins 2017-06-26 05:37:47 -07:00
0c0c9f119f update value proposition 2017-06-26 14:28:03 +08:00
cf77980493 #71 fixed []byte alias 2017-06-26 14:25:56 +08:00
7d681fe2c2 #71 fix map key type of string alias 2017-06-26 11:52:22 +08:00
0c07128d3c #71 sort non string map keys 2017-06-26 10:42:47 +08:00
f771d32291 #70 decode null to nil for map/slice 2017-06-26 10:20:49 +08:00
d100b0d41f fix typo 2017-06-26 10:02:45 +08:00
81e64121ba #71 fix html escape for string alias 2017-06-26 09:57:45 +08:00
dcc91365ee Merge pull request #72 from thockin/output_tests
Output tests
2017-06-26 08:51:10 +08:00
8f3de9c412 Adapt tests to use new Config structs
the unit test uses compatible mode.  The benchmarks measure compat,
default, and fastest.

This still fails for strings and slices and maps all over the place.
2017-06-25 10:29:48 -07:00
5d3508979f Add output tests for slices of builtins 2017-06-25 10:00:35 -07:00
8f8e16b4c2 #63 keep struct field order 2017-06-23 08:21:02 +08:00
d7ea1acd3f #63 fix embed struct at last 2017-06-23 07:45:18 +08:00
ebed7df895 fix unicode and escape 2017-06-22 16:00:47 +08:00
637 changed files with 42883 additions and 9154 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.idea
/coverage.txt
/profile.out

13
.travis.yml Normal file
View File

@ -0,0 +1,13 @@
language: go
go:
- 1.8.x
before_install:
- go get -t -v ./...
script:
- ./test.sh
after_success:
- bash <(curl -s https://codecov.io/bash)

View File

@ -1,6 +1,12 @@
[![Sourcegraph](https://sourcegraph.com/github.com/json-iterator/go/-/badge.svg)](https://sourcegraph.com/github.com/json-iterator/go?badge)
[![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/json-iterator/go)
[![Build Status](https://travis-ci.org/json-iterator/go.svg?branch=master)](https://travis-ci.org/json-iterator/go)
[![codecov](https://codecov.io/gh/json-iterator/go/branch/master/graph/badge.svg)](https://codecov.io/gh/json-iterator/go)
[![rcard](https://goreportcard.com/badge/github.com/json-iterator/go)](https://goreportcard.com/report/github.com/json-iterator/go)
[![License](http://img.shields.io/badge/license-mit-blue.svg?style=flat-square)](https://raw.githubusercontent.com/json-iterator/go/master/LICENSE)
[![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/json-iterator/Lobby)
jsoniter (json-iterator) is fast and flexible JSON parser available in [Java](https://github.com/json-iterator/java) and [Go](https://github.com/json-iterator/go)
A high-performance 100% compatible drop-in replacement of "encoding/json"
# Benchmark
@ -61,4 +67,9 @@ go get github.com/json-iterator/go
# Contribution Welcomed !
Contributors
* [thockin](https://github.com/thockin)
* [cch123](https://github.com/cch123)
Report issue or pull request, or email taowen@gmail.com, or [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/json-iterator/Lobby)

View File

@ -19,6 +19,7 @@ func Test_time_as_int64(t *testing.T) {
}
func Test_time_as_int64_keep_microsecond(t *testing.T) {
t.Skip("conflict")
should := require.New(t)
RegisterTimeAsInt64Codec(time.Microsecond)
output, err := jsoniter.Marshal(time.Unix(1, 1002))

View File

@ -51,6 +51,10 @@ func Marshal(v interface{}) ([]byte, error) {
return ConfigDefault.Marshal(v)
}
func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
return ConfigDefault.MarshalIndent(v, prefix, indent)
}
func MarshalToString(v interface{}) (string, error) {
return ConfigDefault.MarshalToString(v)
}

View File

@ -31,6 +31,7 @@ type frozenConfig struct {
type Api interface {
MarshalToString(v interface{}) (string, error)
Marshal(v interface{}) ([]byte, error)
MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
UnmarshalFromString(str string, v interface{}) error
Unmarshal(data []byte, v interface{}) error
Get(data []byte, path ...interface{}) Any
@ -54,6 +55,7 @@ var ConfigFastest = Config{
}.Froze()
func (cfg Config) Froze() *frozenConfig {
// TODO: cache frozen config
frozenConfig := &frozenConfig{
sortMapKeys: cfg.SortMapKeys,
indentionStep: cfg.IndentionStep,
@ -144,7 +146,6 @@ func (encoder *htmlEscapedStringEncoder) IsEmpty(ptr unsafe.Pointer) bool {
}
func (cfg *frozenConfig) escapeHtml() {
// for better performance
cfg.addEncoderToCache(reflect.TypeOf((*string)(nil)).Elem(), &htmlEscapedStringEncoder{})
}
@ -192,14 +193,14 @@ func (cfg *frozenConfig) getEncoderFromCache(cacheKey reflect.Type) ValEncoder {
func (cfg *frozenConfig) cleanDecoders() {
typeDecoders = map[string]ValDecoder{}
fieldDecoders = map[string]ValDecoder{}
atomic.StorePointer(&cfg.decoderCache, unsafe.Pointer(&map[string]ValDecoder{}))
*cfg = *cfg.configBeforeFrozen.Froze()
}
// cleanEncoders cleans encoders registered or cached
func (cfg *frozenConfig) cleanEncoders() {
typeEncoders = map[string]ValEncoder{}
fieldEncoders = map[string]ValEncoder{}
atomic.StorePointer(&cfg.encoderCache, unsafe.Pointer(&map[string]ValEncoder{}))
*cfg = *cfg.configBeforeFrozen.Froze()
}
func (cfg *frozenConfig) MarshalToString(v interface{}) (string, error) {
@ -225,6 +226,20 @@ func (cfg *frozenConfig) Marshal(v interface{}) ([]byte, error) {
return copied, nil
}
func (cfg *frozenConfig) MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
if prefix != "" {
panic("prefix is not supported")
}
for _, r := range indent {
if r != ' ' {
panic("indent can only be space")
}
}
newCfg := cfg.configBeforeFrozen
newCfg.IndentionStep = len(indent)
return newCfg.Froze().Marshal(v)
}
func (cfg *frozenConfig) UnmarshalFromString(str string, v interface{}) error {
data := []byte(str)
data = data[:lastNotSpacePos(data)]

View File

@ -32,6 +32,10 @@ type ValEncoder interface {
EncodeInterface(val interface{}, stream *Stream)
}
type checkIsEmpty interface {
IsEmpty(ptr unsafe.Pointer) bool
}
func WriteToStream(val interface{}, stream *Stream, encoder ValEncoder) {
e := (*emptyInterface)(unsafe.Pointer(&val))
if e.word == nil {
@ -54,6 +58,7 @@ var jsoniterRawMessageType reflect.Type
var anyType reflect.Type
var marshalerType reflect.Type
var unmarshalerType reflect.Type
var textMarshalerType reflect.Type
var textUnmarshalerType reflect.Type
func init() {
@ -63,6 +68,7 @@ func init() {
anyType = reflect.TypeOf((*Any)(nil)).Elem()
marshalerType = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
unmarshalerType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
}
@ -78,8 +84,9 @@ func (decoder *optionalDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
if *((*unsafe.Pointer)(ptr)) == nil {
//pointer to null, we have to allocate memory to hold the value
value := reflect.New(decoder.valueType)
decoder.valueDecoder.Decode(unsafe.Pointer(value.Pointer()), iter)
*((*uintptr)(ptr)) = value.Pointer()
newPtr := extractInterface(value.Interface()).word
decoder.valueDecoder.Decode(newPtr, iter)
*((*uintptr)(ptr)) = uintptr(newPtr)
} else {
//reuse existing instance
decoder.valueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter)
@ -87,6 +94,25 @@ func (decoder *optionalDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
}
}
type deferenceDecoder struct {
// only to deference a pointer
valueType reflect.Type
valueDecoder ValDecoder
}
func (decoder *deferenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
if *((*unsafe.Pointer)(ptr)) == nil {
//pointer to null, we have to allocate memory to hold the value
value := reflect.New(decoder.valueType)
newPtr := extractInterface(value.Interface()).word
decoder.valueDecoder.Decode(newPtr, iter)
*((*uintptr)(ptr)) = uintptr(newPtr)
} else {
//reuse existing instance
decoder.valueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter)
}
}
type optionalEncoder struct {
valueEncoder ValEncoder
}
@ -107,7 +133,7 @@ func (encoder *optionalEncoder) IsEmpty(ptr unsafe.Pointer) bool {
if *((*unsafe.Pointer)(ptr)) == nil {
return true
} else {
return encoder.valueEncoder.IsEmpty(*((*unsafe.Pointer)(ptr)))
return false
}
}
@ -246,57 +272,123 @@ func decoderOfType(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
}
func createDecoderOfType(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
if typ.String() == "[]uint8" {
return &base64Codec{}, nil
}
if typ.AssignableTo(jsonRawMessageType) {
typeName := typ.String()
if typ == jsonRawMessageType {
return &jsonRawMessageCodec{}, nil
}
if typ.AssignableTo(jsoniterRawMessageType) {
if typ == jsoniterRawMessageType {
return &jsoniterRawMessageCodec{}, nil
}
if typ.AssignableTo(jsonNumberType) {
return &jsonNumberCodec{}, nil
}
if typ.ConvertibleTo(unmarshalerType) {
if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
return &base64Codec{}, nil
}
if typ.Implements(unmarshalerType) {
templateInterface := reflect.New(typ).Elem().Interface()
var decoder ValDecoder = &unmarshalerDecoder{extractInterface(templateInterface)}
if typ.Kind() != reflect.Struct {
decoder = &optionalDecoder{typ, decoder}
if typ.Kind() == reflect.Ptr {
decoder = &optionalDecoder{typ.Elem(), decoder}
}
return decoder, nil
}
if typ.ConvertibleTo(anyType) {
if reflect.PtrTo(typ).Implements(unmarshalerType) {
templateInterface := reflect.New(typ).Interface()
var decoder ValDecoder = &unmarshalerDecoder{extractInterface(templateInterface)}
return decoder, nil
}
if typ.Implements(textUnmarshalerType) {
templateInterface := reflect.New(typ).Elem().Interface()
var decoder ValDecoder = &textUnmarshalerDecoder{extractInterface(templateInterface)}
if typ.Kind() == reflect.Ptr {
decoder = &optionalDecoder{typ.Elem(), decoder}
}
return decoder, nil
}
if reflect.PtrTo(typ).Implements(textUnmarshalerType) {
templateInterface := reflect.New(typ).Interface()
var decoder ValDecoder = &textUnmarshalerDecoder{extractInterface(templateInterface)}
return decoder, nil
}
if typ.Implements(anyType) {
return &anyCodec{}, nil
}
switch typ.Kind() {
case reflect.String:
if typeName != "string" {
return decoderOfType(cfg, reflect.TypeOf((*string)(nil)).Elem())
}
return &stringCodec{}, nil
case reflect.Int:
if typeName != "int" {
return decoderOfType(cfg, reflect.TypeOf((*int)(nil)).Elem())
}
return &intCodec{}, nil
case reflect.Int8:
if typeName != "int8" {
return decoderOfType(cfg, reflect.TypeOf((*int8)(nil)).Elem())
}
return &int8Codec{}, nil
case reflect.Int16:
if typeName != "int16" {
return decoderOfType(cfg, reflect.TypeOf((*int16)(nil)).Elem())
}
return &int16Codec{}, nil
case reflect.Int32:
if typeName != "int32" {
return decoderOfType(cfg, reflect.TypeOf((*int32)(nil)).Elem())
}
return &int32Codec{}, nil
case reflect.Int64:
if typeName != "int64" {
return decoderOfType(cfg, reflect.TypeOf((*int64)(nil)).Elem())
}
return &int64Codec{}, nil
case reflect.Uint:
if typeName != "uint" {
return decoderOfType(cfg, reflect.TypeOf((*uint)(nil)).Elem())
}
return &uintCodec{}, nil
case reflect.Uint8:
if typeName != "uint8" {
return decoderOfType(cfg, reflect.TypeOf((*uint8)(nil)).Elem())
}
return &uint8Codec{}, nil
case reflect.Uint16:
if typeName != "uint16" {
return decoderOfType(cfg, reflect.TypeOf((*uint16)(nil)).Elem())
}
return &uint16Codec{}, nil
case reflect.Uint32:
if typeName != "uint32" {
return decoderOfType(cfg, reflect.TypeOf((*uint32)(nil)).Elem())
}
return &uint32Codec{}, nil
case reflect.Uintptr:
if typeName != "uintptr" {
return decoderOfType(cfg, reflect.TypeOf((*uintptr)(nil)).Elem())
}
return &uintptrCodec{}, nil
case reflect.Uint64:
if typeName != "uint64" {
return decoderOfType(cfg, reflect.TypeOf((*uint64)(nil)).Elem())
}
return &uint64Codec{}, nil
case reflect.Float32:
if typeName != "float32" {
return decoderOfType(cfg, reflect.TypeOf((*float32)(nil)).Elem())
}
return &float32Codec{}, nil
case reflect.Float64:
if typeName != "float64" {
return decoderOfType(cfg, reflect.TypeOf((*float64)(nil)).Elem())
}
return &float64Codec{}, nil
case reflect.Bool:
if typeName != "bool" {
return decoderOfType(cfg, reflect.TypeOf((*bool)(nil)).Elem())
}
return &boolCodec{}, nil
case reflect.Interface:
if typ.NumMethod() == 0 {
@ -305,7 +397,7 @@ func createDecoderOfType(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error
return &nonEmptyInterfaceCodec{}, nil
}
case reflect.Struct:
return prefix(fmt.Sprintf("[%s]", typ.String())).addToDecoder(decoderOfStruct(cfg, typ))
return prefix(fmt.Sprintf("[%s]", typeName)).addToDecoder(decoderOfStruct(cfg, typ))
case reflect.Array:
return prefix("[array]").addToDecoder(decoderOfArray(cfg, typ))
case reflect.Slice:
@ -341,29 +433,55 @@ func encoderOfType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
}
func createEncoderOfType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
if typ.String() == "[]uint8" {
return &base64Codec{}, nil
}
if typ.AssignableTo(jsonRawMessageType) {
if typ == jsonRawMessageType {
return &jsonRawMessageCodec{}, nil
}
if typ.AssignableTo(jsoniterRawMessageType) {
if typ == jsoniterRawMessageType {
return &jsoniterRawMessageCodec{}, nil
}
if typ.AssignableTo(jsonNumberType) {
return &jsonNumberCodec{}, nil
}
if typ.ConvertibleTo(marshalerType) {
if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
return &base64Codec{typ}, nil
}
if typ.Implements(marshalerType) {
checkIsEmpty, err := createCheckIsEmpty(typ)
if err != nil {
return nil, err
}
templateInterface := reflect.New(typ).Elem().Interface()
var encoder ValEncoder = &marshalerEncoder{extractInterface(templateInterface)}
if typ.Kind() != reflect.Struct {
var encoder ValEncoder = &marshalerEncoder{
templateInterface: extractInterface(templateInterface),
checkIsEmpty: checkIsEmpty,
}
if typ.Kind() == reflect.Ptr {
encoder = &optionalEncoder{encoder}
}
return encoder, nil
}
if typ.ConvertibleTo(anyType) {
if typ.Implements(textMarshalerType) {
checkIsEmpty, err := createCheckIsEmpty(typ)
if err != nil {
return nil, err
}
templateInterface := reflect.New(typ).Elem().Interface()
var encoder ValEncoder = &textMarshalerEncoder{
templateInterface: extractInterface(templateInterface),
checkIsEmpty: checkIsEmpty,
}
if typ.Kind() == reflect.Ptr {
encoder = &optionalEncoder{encoder}
}
return encoder, nil
}
if typ.Implements(anyType) {
return &anyCodec{}, nil
}
return createEncoderOfSimpleType(cfg, typ)
}
func createCheckIsEmpty(typ reflect.Type) (checkIsEmpty, error) {
kind := typ.Kind()
switch kind {
case reflect.String:
@ -386,6 +504,8 @@ func createEncoderOfType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error
return &uint16Codec{}, nil
case reflect.Uint32:
return &uint32Codec{}, nil
case reflect.Uintptr:
return &uintptrCodec{}, nil
case reflect.Uint64:
return &uint64Codec{}, nil
case reflect.Float32:
@ -401,7 +521,107 @@ func createEncoderOfType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error
return &nonEmptyInterfaceCodec{}, nil
}
case reflect.Struct:
return prefix(fmt.Sprintf("[%s]", typ.String())).addToEncoder(encoderOfStruct(cfg, typ))
return &structEncoder{}, nil
case reflect.Array:
return &arrayEncoder{}, nil
case reflect.Slice:
return &sliceEncoder{}, nil
case reflect.Map:
return &mapEncoder{}, nil
case reflect.Ptr:
return &optionalEncoder{}, nil
default:
return nil, fmt.Errorf("unsupported type: %v", typ)
}
}
func createEncoderOfSimpleType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
typeName := typ.String()
kind := typ.Kind()
switch kind {
case reflect.String:
if typeName != "string" {
return encoderOfType(cfg, reflect.TypeOf((*string)(nil)).Elem())
}
return &stringCodec{}, nil
case reflect.Int:
if typeName != "int" {
return encoderOfType(cfg, reflect.TypeOf((*int)(nil)).Elem())
}
return &intCodec{}, nil
case reflect.Int8:
if typeName != "int8" {
return encoderOfType(cfg, reflect.TypeOf((*int8)(nil)).Elem())
}
return &int8Codec{}, nil
case reflect.Int16:
if typeName != "int16" {
return encoderOfType(cfg, reflect.TypeOf((*int16)(nil)).Elem())
}
return &int16Codec{}, nil
case reflect.Int32:
if typeName != "int32" {
return encoderOfType(cfg, reflect.TypeOf((*int32)(nil)).Elem())
}
return &int32Codec{}, nil
case reflect.Int64:
if typeName != "int64" {
return encoderOfType(cfg, reflect.TypeOf((*int64)(nil)).Elem())
}
return &int64Codec{}, nil
case reflect.Uint:
if typeName != "uint" {
return encoderOfType(cfg, reflect.TypeOf((*uint)(nil)).Elem())
}
return &uintCodec{}, nil
case reflect.Uint8:
if typeName != "uint8" {
return encoderOfType(cfg, reflect.TypeOf((*uint8)(nil)).Elem())
}
return &uint8Codec{}, nil
case reflect.Uint16:
if typeName != "uint16" {
return encoderOfType(cfg, reflect.TypeOf((*uint16)(nil)).Elem())
}
return &uint16Codec{}, nil
case reflect.Uint32:
if typeName != "uint32" {
return encoderOfType(cfg, reflect.TypeOf((*uint32)(nil)).Elem())
}
return &uint32Codec{}, nil
case reflect.Uintptr:
if typeName != "uintptr" {
return encoderOfType(cfg, reflect.TypeOf((*uintptr)(nil)).Elem())
}
return &uintptrCodec{}, nil
case reflect.Uint64:
if typeName != "uint64" {
return encoderOfType(cfg, reflect.TypeOf((*uint64)(nil)).Elem())
}
return &uint64Codec{}, nil
case reflect.Float32:
if typeName != "float32" {
return encoderOfType(cfg, reflect.TypeOf((*float32)(nil)).Elem())
}
return &float32Codec{}, nil
case reflect.Float64:
if typeName != "float64" {
return encoderOfType(cfg, reflect.TypeOf((*float64)(nil)).Elem())
}
return &float64Codec{}, nil
case reflect.Bool:
if typeName != "bool" {
return encoderOfType(cfg, reflect.TypeOf((*bool)(nil)).Elem())
}
return &boolCodec{}, nil
case reflect.Interface:
if typ.NumMethod() == 0 {
return &emptyInterfaceCodec{}, nil
} else {
return &nonEmptyInterfaceCodec{}, nil
}
case reflect.Struct:
return prefix(fmt.Sprintf("[%s]", typeName)).addToEncoder(encoderOfStruct(cfg, typ))
case reflect.Array:
return prefix("[array]").addToEncoder(encoderOfArray(cfg, typ))
case reflect.Slice:

View File

@ -33,10 +33,6 @@ type arrayEncoder struct {
}
func (encoder *arrayEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
if ptr == nil {
stream.WriteNil()
return
}
stream.WriteArrayStart()
elemPtr := uintptr(ptr)
encoder.elemEncoder.Encode(unsafe.Pointer(elemPtr), stream)
@ -52,7 +48,24 @@ func (encoder *arrayEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
}
func (encoder *arrayEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
// special optimization for interface{}
e := (*emptyInterface)(unsafe.Pointer(&val))
if e.word == nil {
stream.WriteArrayStart()
stream.WriteNil()
stream.WriteArrayEnd()
return
}
elemType := encoder.arrayType.Elem()
if encoder.arrayType.Len() == 1 && (elemType.Kind() == reflect.Ptr || elemType.Kind() == reflect.Map) {
ptr := uintptr(e.word)
e.word = unsafe.Pointer(&ptr)
}
if reflect.TypeOf(val).Kind() == reflect.Ptr {
encoder.Encode(unsafe.Pointer(&e.word), stream)
} else {
encoder.Encode(e.word, stream)
}
}
func (encoder *arrayEncoder) IsEmpty(ptr unsafe.Pointer) bool {

View File

@ -3,6 +3,7 @@ package jsoniter
import (
"fmt"
"reflect"
"sort"
"strings"
"unicode"
"unsafe"
@ -15,6 +16,8 @@ var fieldEncoders = map[string]ValEncoder{}
var extensions = []Extension{}
type StructDescriptor struct {
onePtrEmbedded bool
onePtrOptimization bool
Type reflect.Type
Fields []*Binding
}
@ -29,6 +32,7 @@ func (structDescriptor *StructDescriptor) GetField(fieldName string) *Binding {
}
type Binding struct {
levels []int
Field *reflect.StructField
FromNames []string
ToNames []string
@ -192,35 +196,43 @@ func _getTypeEncoderFromExtension(typ reflect.Type) ValEncoder {
}
func describeStruct(cfg *frozenConfig, typ reflect.Type) (*StructDescriptor, error) {
anonymousBindings := []*Binding{}
embeddedBindings := []*Binding{}
bindings := []*Binding{}
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
if field.Anonymous {
if field.Anonymous && (field.Tag.Get("json") == "" || strings.Split(field.Tag.Get("json"), ",")[0] == "") {
if field.Type.Kind() == reflect.Struct {
structDescriptor, err := describeStruct(cfg, field.Type)
if err != nil {
return nil, err
}
for _, binding := range structDescriptor.Fields {
anonymousBindings = append(anonymousBindings, binding)
binding.levels = append([]int{i}, binding.levels...)
omitempty := binding.Encoder.(*structFieldEncoder).omitempty
binding.Encoder = &structFieldEncoder{&field, binding.Encoder, omitempty}
binding.Decoder = &structFieldDecoder{&field, binding.Decoder}
embeddedBindings = append(embeddedBindings, binding)
}
continue
} else if field.Type.Kind() == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct {
structDescriptor, err := describeStruct(cfg, field.Type.Elem())
if err != nil {
return nil, err
}
for _, binding := range structDescriptor.Fields {
binding.levels = append([]int{i}, binding.levels...)
omitempty := binding.Encoder.(*structFieldEncoder).omitempty
binding.Encoder = &optionalEncoder{binding.Encoder}
binding.Encoder = &structFieldEncoder{&field, binding.Encoder, false}
binding.Decoder = &optionalDecoder{field.Type, binding.Decoder}
binding.Encoder = &structFieldEncoder{&field, binding.Encoder, omitempty}
binding.Decoder = &deferenceDecoder{field.Type.Elem(), binding.Decoder}
binding.Decoder = &structFieldDecoder{&field, binding.Decoder}
anonymousBindings = append(anonymousBindings, binding)
embeddedBindings = append(embeddedBindings, binding)
}
continue
}
}
} else {
tagParts := strings.Split(field.Tag.Get("json"), ",")
fieldNames := calcFieldNames(field.Name, tagParts[0])
fieldNames := calcFieldNames(field.Name, tagParts[0], string(field.Tag.Get("json")))
fieldCacheKey := fmt.Sprintf("%s/%s", typ.String(), field.Name)
decoder := fieldDecoders[fieldCacheKey]
if decoder == nil {
@ -249,16 +261,85 @@ func describeStruct(cfg *frozenConfig, typ reflect.Type) (*StructDescriptor, err
Decoder: decoder,
Encoder: encoder,
}
binding.levels = []int{i}
bindings = append(bindings, binding)
}
return createStructDescriptor(cfg, typ, bindings, embeddedBindings), nil
}
func createStructDescriptor(cfg *frozenConfig, typ reflect.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor {
onePtrEmbedded := false
onePtrOptimization := false
if typ.NumField() == 1 {
firstField := typ.Field(0)
switch firstField.Type.Kind() {
case reflect.Ptr:
if firstField.Anonymous && firstField.Type.Elem().Kind() == reflect.Struct {
onePtrEmbedded = true
}
fallthrough
case reflect.Map:
onePtrOptimization = true
case reflect.Struct:
onePtrOptimization = isStructOnePtr(firstField.Type)
}
}
structDescriptor := &StructDescriptor{
onePtrEmbedded: onePtrEmbedded,
onePtrOptimization: onePtrOptimization,
Type: typ,
Fields: bindings,
}
for _, extension := range extensions {
extension.UpdateStructDescriptor(structDescriptor)
}
processTags(structDescriptor, cfg)
// merge normal & embedded bindings & sort with original order
allBindings := sortableBindings(append(embeddedBindings, structDescriptor.Fields...))
sort.Sort(allBindings)
structDescriptor.Fields = allBindings
return structDescriptor
}
func isStructOnePtr(typ reflect.Type) bool {
if typ.NumField() == 1 {
firstField := typ.Field(0)
switch firstField.Type.Kind() {
case reflect.Ptr:
return true
case reflect.Map:
return true
case reflect.Struct:
return isStructOnePtr(firstField.Type)
}
}
return false
}
type sortableBindings []*Binding
func (bindings sortableBindings) Len() int {
return len(bindings)
}
func (bindings sortableBindings) Less(i, j int) bool {
left := bindings[i].levels
right := bindings[j].levels
k := 0
for {
if left[k] < right[k] {
return true
} else if left[k] > right[k] {
return false
}
k++
}
}
func (bindings sortableBindings) Swap(i, j int) {
bindings[i], bindings[j] = bindings[j], bindings[i]
}
func processTags(structDescriptor *StructDescriptor, cfg *frozenConfig) {
for _, binding := range structDescriptor.Fields {
shouldOmitEmpty := false
tagParts := strings.Split(binding.Field.Tag.Get("json"), ",")
@ -266,34 +347,36 @@ func describeStruct(cfg *frozenConfig, typ reflect.Type) (*StructDescriptor, err
if tagPart == "omitempty" {
shouldOmitEmpty = true
} else if tagPart == "string" {
binding.Decoder = &stringModeDecoder{binding.Decoder}
binding.Encoder = &stringModeEncoder{binding.Encoder}
if binding.Field.Type.Kind() == reflect.String {
binding.Decoder = &stringModeStringDecoder{binding.Decoder, cfg}
binding.Encoder = &stringModeStringEncoder{binding.Encoder, cfg}
} else {
binding.Decoder = &stringModeNumberDecoder{binding.Decoder}
binding.Encoder = &stringModeNumberEncoder{binding.Encoder}
}
}
}
binding.Decoder = &structFieldDecoder{binding.Field, binding.Decoder}
binding.Encoder = &structFieldEncoder{binding.Field, binding.Encoder, shouldOmitEmpty}
}
// insert anonymous bindings to the head
structDescriptor.Fields = append(anonymousBindings, structDescriptor.Fields...)
return structDescriptor, nil
}
func calcFieldNames(originalFieldName string, tagProvidedFieldName string) []string {
// tag => exported? => original
isNotExported := unicode.IsLower(rune(originalFieldName[0]))
func calcFieldNames(originalFieldName string, tagProvidedFieldName string, wholeTag string) []string {
// ignore?
if wholeTag == "-" {
return []string{}
}
// rename?
var fieldNames []string
/// tagParts[0] always present, even if no tags
switch tagProvidedFieldName {
case "":
if tagProvidedFieldName == "" {
fieldNames = []string{originalFieldName}
} else {
fieldNames = []string{tagProvidedFieldName}
}
// private?
isNotExported := unicode.IsLower(rune(originalFieldName[0]))
if isNotExported {
fieldNames = []string{}
} else {
fieldNames = []string{originalFieldName}
}
case "-":
fieldNames = []string{}
default:
fieldNames = []string{tagProvidedFieldName}
}
return fieldNames
}

View File

@ -23,6 +23,10 @@ func (decoder *mapDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
mapInterface.word = ptr
realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
realVal := reflect.ValueOf(*realInterface).Elem()
if iter.ReadNil() {
realVal.Set(reflect.Zero(decoder.mapType))
return
}
if realVal.IsNil() {
realVal.Set(reflect.MakeMap(realVal.Type()))
}
@ -31,9 +35,10 @@ func (decoder *mapDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
decoder.elemDecoder.Decode(unsafe.Pointer(elem.Pointer()), iter)
// to put into map, we have to use reflection
keyType := decoder.keyType
// TODO: remove this from loop
switch {
case keyType.Kind() == reflect.String:
realVal.SetMapIndex(reflect.ValueOf(keyStr), elem.Elem())
realVal.SetMapIndex(reflect.ValueOf(keyStr).Convert(keyType), elem.Elem())
return true
case keyType.Implements(textUnmarshalerType):
textUnmarshaler := reflect.New(keyType.Elem()).Interface().(encoding.TextUnmarshaler)
@ -44,6 +49,15 @@ func (decoder *mapDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
}
realVal.SetMapIndex(reflect.ValueOf(textUnmarshaler), elem.Elem())
return true
case reflect.PtrTo(keyType).Implements(textUnmarshalerType):
textUnmarshaler := reflect.New(keyType).Interface().(encoding.TextUnmarshaler)
err := textUnmarshaler.UnmarshalText([]byte(keyStr))
if err != nil {
iter.ReportError("read map key as TextUnmarshaler", err.Error())
return false
}
realVal.SetMapIndex(reflect.ValueOf(textUnmarshaler).Elem(), elem.Elem())
return true
default:
switch keyType.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
@ -81,7 +95,6 @@ func (encoder *mapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
mapInterface.word = ptr
realInterface := (*interface{})(unsafe.Pointer(&mapInterface))
realVal := reflect.ValueOf(*realInterface)
stream.WriteObjectStart()
for i, key := range realVal.MapKeys() {
if i != 0 {
@ -152,7 +165,15 @@ func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
realVal := reflect.ValueOf(*realInterface)
// Extract and sort the keys.
var sv stringValues = realVal.MapKeys()
keys := realVal.MapKeys()
sv := stringValues(make([]reflectWithString, len(keys)))
for i, v := range keys {
sv[i].v = v
if err := sv[i].resolve(); err != nil {
stream.Error = err
return
}
}
sort.Sort(sv)
stream.WriteObjectStart()
@ -160,9 +181,9 @@ func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
if i != 0 {
stream.WriteMore()
}
encodeMapKey(key, stream)
stream.WriteVal(key.s) // might need html escape, so can not WriteString directly
stream.writeByte(':')
val := realVal.MapIndex(key).Interface()
val := realVal.MapIndex(key.v).Interface()
encoder.elemEncoder.EncodeInterface(val, stream)
}
stream.WriteObjectEnd()
@ -170,12 +191,37 @@ func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
// stringValues is a slice of reflect.Value holding *reflect.StringValue.
// It implements the methods to sort by string.
type stringValues []reflect.Value
type stringValues []reflectWithString
type reflectWithString struct {
v reflect.Value
s string
}
func (w *reflectWithString) resolve() error {
if w.v.Kind() == reflect.String {
w.s = w.v.String()
return nil
}
if tm, ok := w.v.Interface().(encoding.TextMarshaler); ok {
buf, err := tm.MarshalText()
w.s = string(buf)
return err
}
switch w.v.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
w.s = strconv.FormatInt(w.v.Int(), 10)
return nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
w.s = strconv.FormatUint(w.v.Uint(), 10)
return nil
}
return &json.UnsupportedTypeError{w.v.Type()}
}
func (sv stringValues) Len() int { return len(sv) }
func (sv stringValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) }
func (sv stringValues) get(i int) string { return sv[i].String() }
func (sv stringValues) Less(i, j int) bool { return sv[i].s < sv[j].s }
func (encoder *sortKeysMapEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)

View File

@ -1,8 +1,10 @@
package jsoniter
import (
"encoding"
"encoding/base64"
"encoding/json"
"reflect"
"unsafe"
)
@ -45,6 +47,25 @@ func (codec *intCodec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*int)(ptr)) == 0
}
type uintptrCodec struct {
}
func (codec *uintptrCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
*((*uintptr)(ptr)) = uintptr(iter.ReadUint64())
}
func (codec *uintptrCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteUint64(uint64(*((*uintptr)(ptr))))
}
func (encoder *uintptrCodec) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (codec *uintptrCodec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*uintptr)(ptr)) == 0
}
type int8Codec struct {
}
@ -404,26 +425,43 @@ func (encoder *jsoniterRawMessageCodec) IsEmpty(ptr unsafe.Pointer) bool {
}
type base64Codec struct {
actualType reflect.Type
}
func (codec *base64Codec) Decode(ptr unsafe.Pointer, iter *Iterator) {
if iter.ReadNil() {
ptrSlice := (*sliceHeader)(ptr)
ptrSlice.Len = 0
ptrSlice.Cap = 0
ptrSlice.Data = nil
return
}
encoding := base64.StdEncoding
src := iter.SkipAndReturnBytes()
src = src[1 : len(src)-1]
decodedLen := encoding.DecodedLen(len(src))
dst := make([]byte, decodedLen)
_, err := encoding.Decode(dst, src)
len, err := encoding.Decode(dst, src)
if err != nil {
iter.ReportError("decode base64", err.Error())
} else {
*((*[]byte)(ptr)) = dst
dst = dst[:len]
dstSlice := (*sliceHeader)(unsafe.Pointer(&dst))
ptrSlice := (*sliceHeader)(ptr)
ptrSlice.Data = dstSlice.Data
ptrSlice.Cap = dstSlice.Cap
ptrSlice.Len = dstSlice.Len
}
}
func (codec *base64Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
src := *((*[]byte)(ptr))
if len(src) == 0 {
stream.WriteNil()
return
}
encoding := base64.StdEncoding
stream.writeByte('"')
src := *((*[]byte)(ptr))
toGrow := encoding.EncodedLen(len(src))
stream.ensure(toGrow)
encoding.Encode(stream.buf[stream.n:], src)
@ -432,9 +470,14 @@ func (codec *base64Codec) Encode(ptr unsafe.Pointer, stream *Stream) {
}
func (encoder *base64Codec) EncodeInterface(val interface{}, stream *Stream) {
ptr := extractInterface(val).word
src := *((*[]byte)(ptr))
if len(src) == 0 {
stream.WriteNil()
return
}
encoding := base64.StdEncoding
stream.writeByte('"')
src := val.([]byte)
toGrow := encoding.EncodedLen(len(src))
stream.ensure(toGrow)
encoding.Encode(stream.buf[stream.n:], src)
@ -446,14 +489,14 @@ func (encoder *base64Codec) IsEmpty(ptr unsafe.Pointer) bool {
return len(*((*[]byte)(ptr))) == 0
}
type stringModeDecoder struct {
type stringModeNumberDecoder struct {
elemDecoder ValDecoder
}
func (decoder *stringModeDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
func (decoder *stringModeNumberDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
c := iter.nextToken()
if c != '"' {
iter.ReportError("stringModeDecoder", `expect "`)
iter.ReportError("stringModeNumberDecoder", `expect "`)
return
}
decoder.elemDecoder.Decode(ptr, iter)
@ -462,31 +505,65 @@ func (decoder *stringModeDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
}
c = iter.readByte()
if c != '"' {
iter.ReportError("stringModeDecoder", `expect "`)
iter.ReportError("stringModeNumberDecoder", `expect "`)
return
}
}
type stringModeEncoder struct {
type stringModeStringDecoder struct {
elemDecoder ValDecoder
cfg *frozenConfig
}
func (decoder *stringModeStringDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
decoder.elemDecoder.Decode(ptr, iter)
str := *((*string)(ptr))
tempIter := decoder.cfg.BorrowIterator([]byte(str))
defer decoder.cfg.ReturnIterator(tempIter)
*((*string)(ptr)) = tempIter.ReadString()
}
type stringModeNumberEncoder struct {
elemEncoder ValEncoder
}
func (encoder *stringModeEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
func (encoder *stringModeNumberEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.writeByte('"')
encoder.elemEncoder.Encode(ptr, stream)
stream.writeByte('"')
}
func (encoder *stringModeEncoder) EncodeInterface(val interface{}, stream *Stream) {
func (encoder *stringModeNumberEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *stringModeEncoder) IsEmpty(ptr unsafe.Pointer) bool {
func (encoder *stringModeNumberEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.elemEncoder.IsEmpty(ptr)
}
type stringModeStringEncoder struct {
elemEncoder ValEncoder
cfg *frozenConfig
}
func (encoder *stringModeStringEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
tempStream := encoder.cfg.BorrowStream(nil)
defer encoder.cfg.ReturnStream(tempStream)
encoder.elemEncoder.Encode(ptr, tempStream)
stream.WriteString(string(tempStream.Buffer()))
}
func (encoder *stringModeStringEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *stringModeStringEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.elemEncoder.IsEmpty(ptr)
}
type marshalerEncoder struct {
templateInterface emptyInterface
checkIsEmpty checkIsEmpty
}
func (encoder *marshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
@ -506,18 +583,35 @@ func (encoder *marshalerEncoder) EncodeInterface(val interface{}, stream *Stream
}
func (encoder *marshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.checkIsEmpty.IsEmpty(ptr)
}
type textMarshalerEncoder struct {
templateInterface emptyInterface
checkIsEmpty checkIsEmpty
}
func (encoder *textMarshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
templateInterface := encoder.templateInterface
templateInterface.word = ptr
realInterface := (*interface{})(unsafe.Pointer(&templateInterface))
marshaler := (*realInterface).(json.Marshaler)
bytes, err := marshaler.MarshalJSON()
marshaler := (*realInterface).(encoding.TextMarshaler)
bytes, err := marshaler.MarshalText()
if err != nil {
return true
stream.Error = err
} else {
return len(bytes) > 0
stream.WriteString(string(bytes))
}
}
func (encoder *textMarshalerEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder)
}
func (encoder *textMarshalerEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.checkIsEmpty.IsEmpty(ptr)
}
type unmarshalerDecoder struct {
templateInterface emptyInterface
}
@ -527,9 +621,27 @@ func (decoder *unmarshalerDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
templateInterface.word = ptr
realInterface := (*interface{})(unsafe.Pointer(&templateInterface))
unmarshaler := (*realInterface).(json.Unmarshaler)
iter.nextToken()
iter.unreadByte() // skip spaces
bytes := iter.SkipAndReturnBytes()
err := unmarshaler.UnmarshalJSON(bytes)
if err != nil {
iter.ReportError("unmarshaler", err.Error())
iter.ReportError("unmarshalerDecoder", err.Error())
}
}
type textUnmarshalerDecoder struct {
templateInterface emptyInterface
}
func (decoder *textUnmarshalerDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
templateInterface := decoder.templateInterface
templateInterface.word = ptr
realInterface := (*interface{})(unsafe.Pointer(&templateInterface))
unmarshaler := (*realInterface).(encoding.TextUnmarshaler)
str := iter.ReadString()
err := unmarshaler.UnmarshalText([]byte(str))
if err != nil {
iter.ReportError("textUnmarshalerDecoder", err.Error())
}
}

View File

@ -8,32 +8,101 @@ import (
)
func encoderOfStruct(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
fields := map[string]*structFieldEncoder{}
type bindingTo struct {
binding *Binding
toName string
ignored bool
}
orderedBindings := []*bindingTo{}
structDescriptor, err := describeStruct(cfg, typ)
if err != nil {
return nil, err
}
for _, binding := range structDescriptor.Fields {
for _, toName := range binding.ToNames {
fields[toName] = binding.Encoder.(*structFieldEncoder)
new := &bindingTo{
binding: binding,
toName: toName,
}
for _, old := range orderedBindings {
if old.toName != toName {
continue
}
old.ignored, new.ignored = resolveConflictBinding(old.binding, new.binding)
}
orderedBindings = append(orderedBindings, new)
}
}
if len(fields) == 0 {
if len(orderedBindings) == 0 {
return &emptyStructEncoder{}, nil
}
return &structEncoder{fields}, nil
finalOrderedFields := []structFieldTo{}
for _, bindingTo := range orderedBindings {
if !bindingTo.ignored {
finalOrderedFields = append(finalOrderedFields, structFieldTo{
encoder: bindingTo.binding.Encoder.(*structFieldEncoder),
toName: bindingTo.toName,
})
}
}
return &structEncoder{structDescriptor.onePtrEmbedded, structDescriptor.onePtrOptimization, finalOrderedFields}, nil
}
func resolveConflictBinding(old, new *Binding) (ignoreOld, ignoreNew bool) {
newTagged := new.Field.Tag.Get("json") != ""
oldTagged := old.Field.Tag.Get("json") != ""
if newTagged {
if oldTagged {
if len(old.levels) > len(new.levels) {
return true, false
} else if len(new.levels) > len(old.levels) {
return false, true
} else {
return true, true
}
} else {
return true, false
}
} else {
if oldTagged {
return true, false
} else {
if len(old.levels) > len(new.levels) {
return true, false
} else if len(new.levels) > len(old.levels) {
return false, true
} else {
return true, true
}
}
}
}
func decoderOfStruct(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
fields := map[string]*structFieldDecoder{}
bindings := map[string]*Binding{}
structDescriptor, err := describeStruct(cfg, typ)
if err != nil {
return nil, err
}
for _, binding := range structDescriptor.Fields {
for _, fromName := range binding.FromNames {
fields[fromName] = binding.Decoder.(*structFieldDecoder)
old := bindings[fromName]
if old == nil {
bindings[fromName] = binding
continue
}
ignoreOld, ignoreNew := resolveConflictBinding(old, binding)
if ignoreOld {
delete(bindings, fromName)
}
if !ignoreNew {
bindings[fromName] = binding
}
}
}
fields := map[string]*structFieldDecoder{}
for k, binding := range bindings {
fields[k] = binding.Decoder.(*structFieldDecoder)
}
return createStructDecoder(typ, fields)
}
@ -977,61 +1046,54 @@ func (encoder *structFieldEncoder) IsEmpty(ptr unsafe.Pointer) bool {
}
type structEncoder struct {
fields map[string]*structFieldEncoder
onePtrEmbedded bool
onePtrOptimization bool
fields []structFieldTo
}
type structFieldTo struct {
encoder *structFieldEncoder
toName string
}
func (encoder *structEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteObjectStart()
isNotFirst := false
for fieldName, field := range encoder.fields {
if field.omitempty && field.IsEmpty(ptr) {
for _, field := range encoder.fields {
if field.encoder.omitempty && field.encoder.IsEmpty(ptr) {
continue
}
if isNotFirst {
stream.WriteMore()
}
stream.WriteObjectField(fieldName)
field.Encode(ptr, stream)
stream.WriteObjectField(field.toName)
field.encoder.Encode(ptr, stream)
isNotFirst = true
}
stream.WriteObjectEnd()
}
func (encoder *structEncoder) EncodeInterface(val interface{}, stream *Stream) {
var encoderToUse ValEncoder
encoderToUse = encoder
if len(encoder.fields) == 1 {
var firstField *structFieldEncoder
var firstFieldName string
for fieldName, field := range encoder.fields {
firstFieldName = fieldName
firstField = field
e := (*emptyInterface)(unsafe.Pointer(&val))
if encoder.onePtrOptimization {
if e.word == nil && encoder.onePtrEmbedded {
stream.WriteObjectStart()
stream.WriteObjectEnd()
return
}
firstEncoder := firstField.fieldEncoder
firstEncoderName := reflect.TypeOf(firstEncoder).String()
// interface{} has inline optimization for this case
if firstEncoderName == "*jsoniter.optionalEncoder" {
encoderToUse = &structEncoder{
fields: map[string]*structFieldEncoder{
firstFieldName: {
field: firstField.field,
fieldEncoder: firstEncoder.(*optionalEncoder).valueEncoder,
omitempty: firstField.omitempty,
}},
ptr := uintptr(e.word)
e.word = unsafe.Pointer(&ptr)
}
if reflect.TypeOf(val).Kind() == reflect.Ptr {
encoder.Encode(unsafe.Pointer(&e.word), stream)
} else {
encoder.Encode(e.word, stream)
}
}
WriteToStream(val, stream, encoderToUse)
}
func (encoder *structEncoder) IsEmpty(ptr unsafe.Pointer) bool {
for _, field := range encoder.fields {
if !field.IsEmpty(ptr) {
return false
}
}
return true
}
type emptyStructEncoder struct {
}
@ -1045,5 +1107,5 @@ func (encoder *emptyStructEncoder) EncodeInterface(val interface{}, stream *Stre
}
func (encoder *emptyStructEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return true
return false
}

View File

@ -87,6 +87,12 @@ func (decoder *sliceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
func (decoder *sliceDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) {
slice := (*sliceHeader)(ptr)
if iter.ReadNil() {
slice.Len = 0
slice.Cap = 0
slice.Data = nil
return
}
reuseSlice(slice, decoder.sliceType, 4)
if !iter.ReadArray() {
return

View File

@ -225,8 +225,12 @@ func (stream *Stream) WriteObjectStart() {
func (stream *Stream) WriteObjectField(field string) {
stream.WriteString(field)
if stream.indention > 0 {
stream.writeTwoBytes(':', ' ')
} else {
stream.writeByte(':')
}
}
func (stream *Stream) WriteObjectEnd() {
stream.writeIndention(stream.cfg.indentionStep)

View File

@ -2,6 +2,7 @@ package jsoniter
import (
"strconv"
"math"
)
var _POW10 []uint64
@ -11,7 +12,15 @@ func init() {
}
func (stream *Stream) WriteFloat32(val float32) {
stream.WriteRaw(strconv.FormatFloat(float64(val), 'f', -1, 32))
abs := math.Abs(float64(val))
fmt := byte('f')
// Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
if abs != 0 {
if float32(abs) < 1e-6 || float32(abs) >= 1e21 {
fmt = 'e'
}
}
stream.WriteRaw(strconv.FormatFloat(float64(val), fmt, -1, 32))
}
func (stream *Stream) WriteFloat32Lossy(val float32) {
@ -20,7 +29,7 @@ func (stream *Stream) WriteFloat32Lossy(val float32) {
val = -val
}
if val > 0x4ffffff {
stream.WriteRaw(strconv.FormatFloat(float64(val), 'f', -1, 32))
stream.WriteFloat32(val)
return
}
precision := 6
@ -43,7 +52,15 @@ func (stream *Stream) WriteFloat32Lossy(val float32) {
}
func (stream *Stream) WriteFloat64(val float64) {
stream.WriteRaw(strconv.FormatFloat(float64(val), 'f', -1, 64))
abs := math.Abs(val)
fmt := byte('f')
// Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
if abs != 0 {
if abs < 1e-6 || abs >= 1e21 {
fmt = 'e'
}
}
stream.WriteRaw(strconv.FormatFloat(float64(val), fmt, -1, 64))
}
func (stream *Stream) WriteFloat64Lossy(val float64) {
@ -52,7 +69,7 @@ func (stream *Stream) WriteFloat64Lossy(val float64) {
val = -val
}
if val > 0x4ffffff {
stream.WriteRaw(strconv.FormatFloat(val, 'f', -1, 64))
stream.WriteFloat64(val)
return
}
precision := 6

View File

@ -232,7 +232,7 @@ func (stream *Stream) WriteStringWithHtmlEscaped(s string) {
i := 0
for ; i < toWriteLen; i++ {
c := s[i]
if c <= utf8.RuneSelf && htmlSafeSet[c] {
if c < utf8.RuneSelf && htmlSafeSet[c] {
stream.buf[n] = c
n++
} else {
@ -252,7 +252,7 @@ func (stream *Stream) WriteStringWithHtmlEscaped(s string) {
func writeStringSlowPathWithHtmlEscaped(stream *Stream, i int, s string, valLen int) {
start := i
// for the remaining parts, we process them char by char
for ; i < valLen; i++ {
for i < valLen {
if b := s[i]; b < utf8.RuneSelf {
if htmlSafeSet[b] {
i++
@ -351,7 +351,7 @@ func (stream *Stream) WriteString(s string) {
func writeStringSlowPath(stream *Stream, i int, s string, valLen int) {
start := i
// for the remaining parts, we process them char by char
for ; i < valLen; i++ {
for i < valLen {
if b := s[i]; b < utf8.RuneSelf {
if safeSet[b] {
i++
@ -382,10 +382,7 @@ func writeStringSlowPath(stream *Stream, i int, s string, valLen int) {
start = i
continue
}
if start < i {
stream.WriteRaw(s[start:i])
}
start = i
i++
continue
}
if start < len(s) {

View File

@ -0,0 +1,44 @@
// +build go1.8
package jsoniter
import (
"testing"
"encoding/json"
"github.com/json-iterator/go/require"
"bytes"
"unicode/utf8"
)
func Test_new_encoder(t *testing.T) {
should := require.New(t)
buf1 := &bytes.Buffer{}
encoder1 := json.NewEncoder(buf1)
encoder1.SetEscapeHTML(false)
encoder1.Encode([]int{1})
should.Equal("[1]\n", buf1.String())
buf2 := &bytes.Buffer{}
encoder2 := NewEncoder(buf2)
encoder2.SetEscapeHTML(false)
encoder2.Encode([]int{1})
should.Equal("[1]", buf2.String())
}
func Test_string_encode_with_std_without_html_escape(t *testing.T) {
api := Config{EscapeHtml: false}.Froze()
should := require.New(t)
for i := 0; i < utf8.RuneSelf; i++ {
input := string([]byte{byte(i)})
buf := &bytes.Buffer{}
encoder := json.NewEncoder(buf)
encoder.SetEscapeHTML(false)
err := encoder.Encode(input)
should.Nil(err)
stdOutput := buf.String()
stdOutput = stdOutput[:len(stdOutput)-1]
jsoniterOutputBytes, err := api.Marshal(input)
should.Nil(err)
jsoniterOutput := string(jsoniterOutputBytes)
should.Equal(stdOutput, jsoniterOutput)
}
}

View File

@ -33,20 +33,6 @@ func Test_new_decoder(t *testing.T) {
should.False(decoder2.More())
}
func Test_new_encoder(t *testing.T) {
should := require.New(t)
buf1 := &bytes.Buffer{}
encoder1 := json.NewEncoder(buf1)
encoder1.SetEscapeHTML(false)
encoder1.Encode([]int{1})
should.Equal("[1]\n", buf1.String())
buf2 := &bytes.Buffer{}
encoder2 := NewEncoder(buf2)
encoder2.SetEscapeHTML(false)
encoder2.Encode([]int{1})
should.Equal("[1]", buf2.String())
}
func Test_use_number(t *testing.T) {
should := require.New(t)
decoder1 := json.NewDecoder(bytes.NewBufferString(`123`))
@ -68,3 +54,17 @@ func Test_use_number_for_unmarshal(t *testing.T) {
should.Nil(api.UnmarshalFromString("123", &obj))
should.Equal(json.Number("123"), obj)
}
func Test_marshal_indent(t *testing.T) {
should := require.New(t)
obj := struct {
F1 int
F2 []int
}{1, []int{2, 3, 4}}
output, err := json.MarshalIndent(obj, "", " ")
should.Nil(err)
should.Equal("{\n \"F1\": 1,\n \"F2\": [\n 2,\n 3,\n 4\n ]\n}", string(output))
output, err = MarshalIndent(obj, "", " ")
should.Nil(err)
should.Equal("{\n \"F1\": 1,\n \"F2\": [\n 2,\n 3,\n 4\n ]\n}", string(output))
}

View File

@ -118,25 +118,6 @@ func Test_customize_field_by_extension(t *testing.T) {
should.Equal(`{"field-1":100}`, str)
}
//func Test_unexported_fields(t *testing.T) {
// jsoniter := Config{SupportUnexportedStructFields: true}.Froze()
// should := require.New(t)
// type TestObject struct {
// field1 string
// field2 string `json:"field-2"`
// }
// obj := TestObject{}
// obj.field1 = "hello"
// should.Nil(jsoniter.UnmarshalFromString(`{}`, &obj))
// should.Equal("hello", obj.field1)
// should.Nil(jsoniter.UnmarshalFromString(`{"field1": "world", "field-2": "abc"}`, &obj))
// should.Equal("world", obj.field1)
// should.Equal("abc", obj.field2)
// str, err := jsoniter.MarshalToString(obj)
// should.Nil(err)
// should.Contains(str, `"field-2":"abc"`)
//}
type timeImplementedMarshaler time.Time
func (obj timeImplementedMarshaler) MarshalJSON() ([]byte, error) {
@ -180,26 +161,22 @@ func Test_marshaler_and_encoder(t *testing.T) {
type ObjectImplementedUnmarshaler int
func (obj *ObjectImplementedUnmarshaler) UnmarshalJSON([]byte) error {
*obj = 100
func (obj *ObjectImplementedUnmarshaler) UnmarshalJSON(s []byte) error {
val, _ := strconv.ParseInt(string(s[1:len(s)-1]), 10, 64)
*obj = ObjectImplementedUnmarshaler(val)
return nil
}
func Test_unmarshaler(t *testing.T) {
type TestObject struct {
Field *ObjectImplementedUnmarshaler
Field2 string
}
should := require.New(t)
obj := TestObject{}
val := ObjectImplementedUnmarshaler(0)
obj.Field = &val
err := json.Unmarshal([]byte(`{"Field":"hello"}`), &obj)
var obj ObjectImplementedUnmarshaler
err := json.Unmarshal([]byte(` "100" `), &obj)
should.Nil(err)
should.Equal(100, int(*obj.Field))
err = Unmarshal([]byte(`{"Field":"hello"}`), &obj)
should.Equal(100, int(obj))
iter := ParseString(ConfigDefault, ` "100" `)
iter.ReadVal(&obj)
should.Nil(err)
should.Equal(100, int(*obj.Field))
should.Equal(100, int(obj))
}
func Test_unmarshaler_and_decoder(t *testing.T) {
@ -216,10 +193,10 @@ func Test_unmarshaler_and_decoder(t *testing.T) {
obj := TestObject{}
val := ObjectImplementedUnmarshaler(0)
obj.Field = &val
err := json.Unmarshal([]byte(`{"Field":"hello"}`), &obj)
err := json.Unmarshal([]byte(`{"Field":"100"}`), &obj)
should.Nil(err)
should.Equal(100, int(*obj.Field))
err = Unmarshal([]byte(`{"Field":"hello"}`), &obj)
err = Unmarshal([]byte(`{"Field":"100"}`), &obj)
should.Nil(err)
should.Equal(10, int(*obj.Field))
}
@ -242,3 +219,69 @@ func Test_marshaler_on_struct(t *testing.T) {
//json.Marshal(fixed)
Marshal(fixed)
}
type withChan struct {
F2 chan []byte
}
func (q withChan) MarshalJSON() ([]byte, error) {
return []byte(`""`), nil
}
func (q *withChan) UnmarshalJSON(value []byte) error {
return nil
}
func Test_marshal_json_with_chan(t *testing.T) {
type TestObject struct {
F1 withChan
}
should := require.New(t)
output, err := MarshalToString(TestObject{})
should.Nil(err)
should.Equal(`{"F1":""}`, output)
}
type withTime struct {
time.Time
}
func (t *withTime) UnmarshalJSON(b []byte) error {
return nil
}
func (t withTime) MarshalJSON() ([]byte, error) {
return []byte(`"fake"`), nil
}
func Test_marshal_json_with_time(t *testing.T) {
type S1 struct {
F1 withTime
F2 *withTime
}
type TestObject struct {
TF1 S1
}
should := require.New(t)
obj := TestObject{
S1{
F1: withTime{
time.Unix(0, 0),
},
F2: &withTime{
time.Unix(0, 0),
},
},
}
output, err := json.Marshal(obj)
should.Nil(err)
should.Equal(`{"TF1":{"F1":"fake","F2":"fake"}}`, string(output))
output, err = Marshal(obj)
should.Nil(err)
should.Equal(`{"TF1":{"F1":"fake","F2":"fake"}}`, string(output))
obj = TestObject{}
should.Nil(json.Unmarshal([]byte(`{"TF1":{"F1":"fake","F2":"fake"}}`), &obj))
should.NotNil(obj.TF1.F2)
obj = TestObject{}
should.Nil(Unmarshal([]byte(`{"TF1":{"F1":"fake","F2":"fake"}}`), &obj))
should.NotNil(obj.TF1.F2)
}

View File

@ -1,3 +1,5 @@
// +build go1.8
package jsoniter
import (
@ -85,7 +87,9 @@ func Test_write_float32(t *testing.T) {
stream.WriteFloat32Lossy(val)
stream.Flush()
should.Nil(stream.Error)
should.Equal(strconv.FormatFloat(float64(val), 'f', -1, 32), buf.String())
output, err := json.Marshal(val)
should.Nil(err)
should.Equal(string(output), buf.String())
})
t.Run(fmt.Sprintf("%v", val), func(t *testing.T) {
should := require.New(t)
@ -94,7 +98,9 @@ func Test_write_float32(t *testing.T) {
stream.WriteVal(val)
stream.Flush()
should.Nil(stream.Error)
should.Equal(strconv.FormatFloat(float64(val), 'f', -1, 32), buf.String())
output, err := json.Marshal(val)
should.Nil(err)
should.Equal(string(output), buf.String())
})
}
should := require.New(t)

View File

@ -1,3 +1,5 @@
// +build go1.8
package jsoniter
import (

View File

@ -162,3 +162,129 @@ func Test_read_large_number_as_interface(t *testing.T) {
should.Nil(err)
should.Equal(`123456789123456789123456789`, output)
}
func Test_nested_one_field_struct(t *testing.T) {
should := require.New(t)
type YetYetAnotherObject struct {
Field string
}
type YetAnotherObject struct {
Field *YetYetAnotherObject
}
type AnotherObject struct {
Field *YetAnotherObject
}
type TestObject struct {
Me *AnotherObject
}
obj := TestObject{&AnotherObject{&YetAnotherObject{&YetYetAnotherObject{"abc"}}}}
str, err := MarshalToString(obj)
should.Nil(err)
should.Equal(`{"Me":{"Field":{"Field":{"Field":"abc"}}}}`, str)
str, err = MarshalToString(&obj)
should.Nil(err)
should.Equal(`{"Me":{"Field":{"Field":{"Field":"abc"}}}}`, str)
}
func Test_struct_with_embedded_ptr_with_tag(t *testing.T) {
type O1 struct {
O1F string
}
type Option struct {
O1 *O1
}
type T struct {
Option `json:","`
}
var obj T
should := require.New(t)
output, err := MarshalToString(obj)
should.Nil(err)
should.Equal(`{"O1":null}`, output)
}
func Test_struct_with_one_nil(t *testing.T) {
type TestObject struct {
F *float64
}
var obj TestObject
should := require.New(t)
output, err := MarshalToString(obj)
should.Nil(err)
should.Equal(`{"F":null}`, output)
}
func Test_struct_with_one_nil_embedded(t *testing.T) {
type Parent struct {
Field1 string
Field2 string
}
type TestObject struct {
*Parent
}
obj := TestObject{}
should := require.New(t)
bytes, err := json.Marshal(obj)
should.Nil(err)
should.Equal("{}", string(bytes))
output, err := MarshalToString(obj)
should.Nil(err)
should.Equal(`{}`, output)
}
func Test_struct_with_not_nil_embedded(t *testing.T) {
type Parent struct {
Field0 string
Field1 []string
Field2 map[string]interface{}
}
type TestObject struct {
*Parent
}
should := require.New(t)
var obj TestObject
err := UnmarshalFromString(`{"Field0":"1","Field1":null,"Field2":{"K":"V"}}`, &obj)
should.Nil(err)
should.Nil(obj.Field1)
should.Equal(map[string]interface{}{"K": "V"}, obj.Field2)
should.Equal("1", obj.Field0)
}
func Test_array_with_one_nil_ptr(t *testing.T) {
obj := [1]*float64{nil}
should := require.New(t)
output, err := MarshalToString(obj)
should.Nil(err)
should.Equal(`[null]`, output)
}
func Test_array_with_one_not_nil_ptr(t *testing.T) {
two := float64(2)
obj := [1]*float64{&two}
should := require.New(t)
output, err := MarshalToString(obj)
should.Nil(err)
should.Equal(`[2]`, output)
}
func Test_embedded_array_with_one_nil(t *testing.T) {
type TestObject struct {
Field1 int
Field2 [1]*float64
}
var obj TestObject
should := require.New(t)
output, err := MarshalToString(obj)
should.Nil(err)
should.Contains(output, `"Field2":[null]`)
}
func Test_array_with_nothing(t *testing.T) {
var obj [2]*float64
should := require.New(t)
output, err := MarshalToString(obj)
should.Nil(err)
should.Equal(`[null,null]`, output)
}

View File

@ -32,7 +32,7 @@ func Test_encode_null(t *testing.T) {
should.Equal("null", str)
}
func Test_decode_null_object(t *testing.T) {
func Test_decode_null_object_field(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, `[null,"a"]`)
iter.ReadArray()
@ -51,16 +51,27 @@ func Test_decode_null_object(t *testing.T) {
should.Len(objs, 1)
}
func Test_decode_null_array(t *testing.T) {
func Test_decode_null_array_element(t *testing.T) {
should := require.New(t)
iter := ParseString(ConfigDefault, `[null,"a"]`)
iter.ReadArray()
if iter.ReadArray() != false {
t.FailNow()
should.True(iter.ReadArray())
should.True(iter.ReadNil())
should.True(iter.ReadArray())
should.Equal("a", iter.ReadString())
}
iter.ReadArray()
if iter.ReadString() != "a" {
t.FailNow()
func Test_decode_null_array(t *testing.T) {
should := require.New(t)
arr := []string{}
should.Nil(UnmarshalFromString("null", &arr))
should.Nil(arr)
}
func Test_decode_null_map(t *testing.T) {
should := require.New(t)
arr := map[string]string{}
should.Nil(UnmarshalFromString("null", &arr))
should.Nil(arr)
}
func Test_decode_null_string(t *testing.T) {

View File

@ -280,29 +280,6 @@ func Test_recursive_struct(t *testing.T) {
should.Nil(err)
}
func Test_one_field_struct(t *testing.T) {
should := require.New(t)
type YetYetAnotherObject struct {
Field string
}
type YetAnotherObject struct {
Field *YetYetAnotherObject
}
type AnotherObject struct {
Field *YetAnotherObject
}
type TestObject struct {
Me *AnotherObject
}
obj := TestObject{&AnotherObject{&YetAnotherObject{&YetYetAnotherObject{"abc"}}}}
str, err := MarshalToString(obj)
should.Nil(err)
should.Equal(`{"Me":{"Field":{"Field":{"Field":"abc"}}}}`, str)
str, err = MarshalToString(&obj)
should.Nil(err)
should.Equal(`{"Me":{"Field":{"Field":{"Field":"abc"}}}}`, str)
}
func Test_encode_anonymous_struct(t *testing.T) {
should := require.New(t)
type TestObject struct {
@ -349,10 +326,7 @@ func Test_multiple_level_anonymous_struct(t *testing.T) {
obj := Level3{Level2{Level1{"1"}, "2"}, "3"}
output, err := MarshalToString(obj)
should.Nil(err)
fmt.Println(output)
should.Contains(output, `"Field1":"1"`)
should.Contains(output, `"Field2":"2"`)
should.Contains(output, `"Field3":"3"`)
should.Equal(`{"Field1":"1","Field2":"2","Field3":"3"}`, output)
}
func Test_multiple_level_anonymous_struct_with_ptr(t *testing.T) {
@ -407,6 +381,35 @@ func Test_shadow_struct_field(t *testing.T) {
should.Contains(output, `"max_age":20`)
}
func Test_embeded_order(t *testing.T) {
type A struct {
Field2 string
}
type C struct {
Field5 string
}
type B struct {
Field4 string
C
Field6 string
}
type TestObject struct {
Field1 string
A
Field3 string
B
Field7 string
}
should := require.New(t)
s := TestObject{}
output, err := MarshalToString(s)
should.Nil(err)
should.Equal(`{"Field1":"","Field2":"","Field3":"","Field4":"","Field5":"","Field6":"","Field7":""}`, output)
}
func Test_decode_nested(t *testing.T) {
type StructOfString struct {
Field1 string

View File

@ -1,3 +1,5 @@
// +build go1.8
package jsoniter
import (
@ -101,6 +103,10 @@ func Test_html_escape(t *testing.T) {
output, err = ConfigCompatibleWithStandardLibrary.Marshal(`>`)
should.Nil(err)
should.Equal(`"\u003e"`, string(output))
type MyString string
output, err = ConfigCompatibleWithStandardLibrary.Marshal(MyString(`>`))
should.Nil(err)
should.Equal(`"\u003e"`, string(output))
}
func Test_string_encode_with_std(t *testing.T) {
@ -117,25 +123,6 @@ func Test_string_encode_with_std(t *testing.T) {
}
}
func Test_string_encode_with_std_without_html_escape(t *testing.T) {
api := Config{EscapeHtml: false}.Froze()
should := require.New(t)
for i := 0; i < utf8.RuneSelf; i++ {
input := string([]byte{byte(i)})
buf := &bytes.Buffer{}
encoder := json.NewEncoder(buf)
encoder.SetEscapeHTML(false)
err := encoder.Encode(input)
should.Nil(err)
stdOutput := buf.String()
stdOutput = stdOutput[:len(stdOutput)-1]
jsoniterOutputBytes, err := api.Marshal(input)
should.Nil(err)
jsoniterOutput := string(jsoniterOutputBytes)
should.Equal(stdOutput, jsoniterOutput)
}
}
func Test_unicode(t *testing.T) {
should := require.New(t)
output, _ := MarshalToString(map[string]interface{}{"a": "数字山谷"})
@ -144,6 +131,27 @@ func Test_unicode(t *testing.T) {
should.Equal(`{"a":"数字山谷"}`, output)
}
func Test_unicode_and_escape(t *testing.T) {
should := require.New(t)
output, err := MarshalToString(`"数字山谷"`)
should.Nil(err)
should.Equal(`"\"数字山谷\""`, output)
output, err = ConfigFastest.MarshalToString(`"数字山谷"`)
should.Nil(err)
should.Equal(`"\"数字山谷\""`, output)
}
func Test_unsafe_unicode(t *testing.T) {
ConfigDefault.cleanEncoders()
should := require.New(t)
output, err := ConfigDefault.MarshalToString("he\u2029\u2028he")
should.Nil(err)
should.Equal(`"he\u2029\u2028he"`, output)
output, err = ConfigFastest.MarshalToString("he\u2029\u2028he")
should.Nil(err)
should.Equal("\"he\u2029\u2028he\"", output)
}
func Benchmark_jsoniter_unicode(b *testing.B) {
for n := 0; n < b.N; n++ {
iter := ParseString(ConfigDefault, `"\ud83d\udc4a"`)

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4][4]bool

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4][4]byte

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4][4]float64

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4][4]int32

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4][4]*string

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4][4]string

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4][4]uint8

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4]bool

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4]byte

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4]float64

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4]int32

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4]map[int32]string

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4]map[string]string

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4]*bool

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4]*float64

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4]*int32

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4]*map[int32]string

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4]*map[string]string

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4]*[4]bool

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4]*[4]byte

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4]*[4]float64

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4]*[4]int32

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4]*[4]*string

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4]*[4]string

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4]*[4]uint8

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4]*string

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,12 @@
package test
type T [4]*struct {
String string
Int int32
Float float64
Struct struct {
X string
}
Slice [4]string
Map map[string]string
}

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4]*uint8

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4][4]bool

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4][4]byte

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4][4]float64

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4][4]int32

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4][4]*string

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4][4]string

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4][4]uint8

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4]string

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

View File

@ -0,0 +1,3 @@
package test
type T [4]struct{}

View File

@ -0,0 +1,152 @@
package test
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
fuzz "github.com/google/gofuzz"
jsoniter "github.com/json-iterator/go"
)
func Test_Roundtrip(t *testing.T) {
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
for i := 0; i < 100; i++ {
var before T
fz.Fuzz(&before)
jbStd, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with stdlib: %v", err)
}
if len(strings.TrimSpace(string(jbStd))) == 0 {
t.Fatal("stdlib marshal produced empty result and no error")
}
jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal with jsoniter: %v", err)
}
if len(strings.TrimSpace(string(jbIter))) == 0 {
t.Fatal("jsoniter marshal produced empty result and no error")
}
if string(jbStd) != string(jbIter) {
t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
indent(jbStd, " "), indent(jbIter, " "), dump(before))
}
var afterStd T
err = json.Unmarshal(jbIter, &afterStd)
if err != nil {
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
var afterIter T
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
if err != nil {
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
err, indent(jbIter, " "))
}
if fingerprint(afterStd) != fingerprint(afterIter) {
t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
dump(afterStd), dump(afterIter), indent(jbIter, " "))
}
}
}
const indentStr = "> "
func fingerprint(obj interface{}) string {
c := spew.ConfigState{
SortKeys: true,
SpewKeys: true,
}
return c.Sprintf("%v", obj)
}
func dump(obj interface{}) string {
cfg := spew.ConfigState{
Indent: indentStr,
}
return cfg.Sdump(obj)
}
func indent(src []byte, prefix string) string {
var buf bytes.Buffer
err := json.Indent(&buf, src, prefix, indentStr)
if err != nil {
return fmt.Sprintf("!!! %v", err)
}
return buf.String()
}
func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
t.ReportAllocs()
t.ResetTimer()
var obj T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&obj)
for i := 0; i < t.N; i++ {
jb, err := fn(obj)
if err != nil {
t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
}
_ = jb
}
}
func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
t.ReportAllocs()
t.ResetTimer()
var before T
fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
fz.Fuzz(&before)
jb, err := json.Marshal(before)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
for i := 0; i < t.N; i++ {
var after T
err = fn(jb, &after)
if err != nil {
t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
}
}
}
func BenchmarkStandardMarshal(t *testing.B) {
benchmarkMarshal(t, "stdlib", json.Marshal)
}
func BenchmarkStandardUnmarshal(t *testing.B) {
benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
}
func BenchmarkJSONIterMarshalFastest(t *testing.B) {
benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
}
func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
}
func BenchmarkJSONIterMarshalDefault(t *testing.B) {
benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
}
func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
}
func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
}
func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
}

Some files were not shown because too many files have changed in this diff Show More