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

20 Commits

Author SHA1 Message Date
0ff49de124 update README 2019-03-06 22:29:09 +08:00
5bc9320502 Merge pull request #316 from proemergotech/master
fix #308 do NOT skip embedded structs without tag when OnlyTaggedFiel…
2019-02-08 15:56:42 +08:00
f64ce68b6e Merge pull request #338 from dvrkps/master
Clean go vet error and ineffassign warnings.
2019-01-14 23:53:30 +08:00
2d42ff74dd Merge pull request #337 from denverdino/fix-encode-with-MarshalJSON
Fix the incompatible encoding #336
2019-01-14 23:52:16 +08:00
3a023a5fbc clean readPositiveFloat64 2019-01-10 18:00:15 +01:00
16aef10b2b clean readPositiveFloat32 2019-01-10 17:55:28 +01:00
ae4c002f78 rename ExampleMyKey 2019-01-10 17:51:25 +01:00
e4aa2ec063 Fix the incompatible encoding 2019-01-03 18:19:22 +08:00
d05f387f50 fix #317, try parse as BigFloat if overflow 2018-11-12 14:45:56 +08:00
a9403d25cd fix #308 do NOT skip embedded structs without tag when OnlyTaggedField is set to true 2018-10-29 12:00:51 +01:00
05d041de10 fix #313 support json marshaller type as map key 2018-10-24 23:28:41 +08:00
5916df66b3 fix #311 handle nil any 2018-10-24 21:05:37 +08:00
2433035e51 Merge pull request #304 from Quasilyte/quasilyte/emptyFallthrough
use multi-value case clause instead of fallthrough
2018-09-14 09:48:43 +08:00
6dfc0bf2dd Merge pull request #305 from Quasilyte/quasilyte/assignOp
simplify `x = x <op> y` to `x <op>= y`
2018-09-14 09:48:25 +08:00
b9be8dd373 Merge pull request #306 from Quasilyte/quasilyte/underef
remove redundant dereferencing expressions
2018-09-14 09:47:54 +08:00
b8d78b6aaf Merge pull request #307 from Quasilyte/quasilyte/commentedOutCode
any_tests: remove commented-out code
2018-09-14 09:47:25 +08:00
7109b5e7dd any_tests: remove commented-out code
Found using https://go-critic.github.io/overview#commentedOutCode-ref
2018-09-13 21:57:53 +03:00
4cc76529e8 remove redundant dereferencing expressions
Found using https://go-critic.github.io/overview#underef-ref
2018-09-13 21:51:59 +03:00
c5ddac9dc3 simplify x = x <op> y to x <op>= y
Found using https://go-critic.github.io/overview#assignOp-ref
2018-09-13 21:48:13 +03:00
f76d712086 use multi-value case clause instead of fallthrough
Found using https://go-critic.github.io/overview#emptyFallthrough-ref
2018-09-13 21:43:37 +03:00
20 changed files with 235 additions and 56 deletions

View File

@ -10,10 +10,6 @@ A high-performance 100% compatible drop-in replacement of "encoding/json"
You can also use thrift like JSON using [thrift-iterator](https://github.com/thrift-iterator/go)
```
Go开发者们请加入我们,滴滴出行平台技术部 taowen@didichuxing.com
```
# Benchmark
![benchmark](http://jsoniter.com/benchmarks/go-benchmark.png)

4
any.go
View File

@ -312,6 +312,10 @@ func (codec *directAnyCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
func (codec *directAnyCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
any := *(*Any)(ptr)
if any == nil {
stream.WriteNil()
return
}
any.WriteTo(stream)
}

View File

@ -82,10 +82,8 @@ func Test_read_float_to_any(t *testing.T) {
should := require.New(t)
any := jsoniter.WrapFloat64(12.3)
anyFloat64 := float64(12.3)
//negaAnyFloat64 := float64(-1.1)
any2 := jsoniter.WrapFloat64(-1.1)
should.Equal(float64(12.3), any.ToFloat64())
//should.Equal("12.3", any.ToString())
should.True(any.ToBool())
should.Equal(float32(anyFloat64), any.ToFloat32())
should.Equal(int(anyFloat64), any.ToInt())

View File

@ -118,6 +118,4 @@ func Test_object_wrapper_any_get_all(t *testing.T) {
should.Contains(any.Keys(), "Field1")
should.Contains(any.Keys(), "Field2")
should.NotContains(any.Keys(), "Field3")
//should.Contains(any.GetObject()["Field1"].GetArray()[0], 1)
}

View File

@ -172,3 +172,58 @@ func Test_CaseSensitive_MoreThanTenFields(t *testing.T) {
should.Equal(tc.expectedOutput, output)
}
}
type onlyTaggedFieldStruct struct {
A string `json:"a"`
B string
FSimpl F `json:"f_simpl"`
ISimpl I
FPtr *F `json:"f_ptr"`
IPtr *I
F
*I
}
type F struct {
G string `json:"g"`
H string
}
type I struct {
J string `json:"j"`
K string
}
func Test_OnlyTaggedField(t *testing.T) {
should := require.New(t)
obj := onlyTaggedFieldStruct{
A: "a",
B: "b",
FSimpl: F{G: "g", H: "h"},
ISimpl: I{J: "j", K: "k"},
FPtr: &F{G: "g", H: "h"},
IPtr: &I{J: "j", K: "k"},
F: F{G: "g", H: "h"},
I: &I{J: "j", K: "k"},
}
output, err := jsoniter.Config{OnlyTaggedField: true}.Froze().Marshal(obj)
should.Nil(err)
m := make(map[string]interface{})
err = jsoniter.Unmarshal(output, &m)
should.Nil(err)
should.Equal(map[string]interface{}{
"a": "a",
"f_simpl": map[string]interface{}{
"g": "g",
},
"f_ptr": map[string]interface{}{
"g": "g",
},
"g": "g",
"j": "j",
}, m)
}

View File

@ -0,0 +1,36 @@
package test
import (
"bytes"
"encoding/json"
"github.com/json-iterator/go"
"testing"
"github.com/stretchr/testify/require"
)
type Foo struct {
Bar interface{}
}
func (f Foo) MarshalJSON() ([]byte, error) {
var buf bytes.Buffer
err := json.NewEncoder(&buf).Encode(f.Bar)
return buf.Bytes(), err
}
// Standard Encoder has trailing newline.
func TestEncodeMarshalJSON(t *testing.T) {
foo := Foo {
Bar: 123,
}
should := require.New(t)
var buf, stdbuf bytes.Buffer
enc := jsoniter.ConfigCompatibleWithStandardLibrary.NewEncoder(&buf)
enc.Encode(foo)
stdenc := json.NewEncoder(&stdbuf)
stdenc.Encode(foo)
should.Equal(stdbuf.Bytes(), buf.Bytes())
}

View File

@ -95,7 +95,7 @@ func ExampleGet() {
// Crimson
}
func ExampleMapKey() {
func ExampleMyKey() {
hello := MyKey("hello")
output, _ := Marshal(map[*MyKey]string{&hello: "world"})
fmt.Println(string(output))

View File

@ -1,13 +1,13 @@
package test
import (
"bytes"
"github.com/json-iterator/go"
"github.com/stretchr/testify/require"
"strconv"
"testing"
"time"
"unsafe"
"bytes"
)
func Test_customize_type_decoder(t *testing.T) {

View File

@ -153,7 +153,7 @@ func (codec *binaryAsStringCodec) Decode(ptr unsafe.Pointer, iter *jsoniter.Iter
}
b4 := rawBytes[i+3]
b5 := rawBytes[i+4]
i = i + 4
i += 4
b = readHex(iter, b4, b5)
}
bytes = append(bytes, b)
@ -178,7 +178,7 @@ func readHex(iter *jsoniter.Iterator, b1, b2 byte) byte {
iter.ReportError("read hex", "expects 0~9 or a~f, but found "+string([]byte{b1}))
return 0
}
ret = ret * 16
ret *= 16
if b2 >= '0' && b2 <= '9' {
ret = b2 - '0'
} else if b2 >= 'a' && b2 <= 'f' {

View File

@ -77,14 +77,12 @@ func (iter *Iterator) ReadFloat32() (ret float32) {
}
func (iter *Iterator) readPositiveFloat32() (ret float32) {
value := uint64(0)
c := byte(' ')
i := iter.head
// first char
if i == iter.tail {
return iter.readFloat32SlowPath()
}
c = iter.buf[i]
c := iter.buf[i]
i++
ind := floatDigits[c]
switch ind {
@ -107,7 +105,7 @@ func (iter *Iterator) readPositiveFloat32() (ret float32) {
return
}
}
value = uint64(ind)
value := uint64(ind)
// chars before dot
non_decimal_loop:
for ; i < iter.tail; i++ {
@ -145,9 +143,7 @@ non_decimal_loop:
}
// too many decimal places
return iter.readFloat32SlowPath()
case invalidCharForNumber:
fallthrough
case dotInNumber:
case invalidCharForNumber, dotInNumber:
return iter.readFloat32SlowPath()
}
decimalPlaces++
@ -218,14 +214,12 @@ func (iter *Iterator) ReadFloat64() (ret float64) {
}
func (iter *Iterator) readPositiveFloat64() (ret float64) {
value := uint64(0)
c := byte(' ')
i := iter.head
// first char
if i == iter.tail {
return iter.readFloat64SlowPath()
}
c = iter.buf[i]
c := iter.buf[i]
i++
ind := floatDigits[c]
switch ind {
@ -248,7 +242,7 @@ func (iter *Iterator) readPositiveFloat64() (ret float64) {
return
}
}
value = uint64(ind)
value := uint64(ind)
// chars before dot
non_decimal_loop:
for ; i < iter.tail; i++ {
@ -286,9 +280,7 @@ non_decimal_loop:
}
// too many decimal places
return iter.readFloat64SlowPath()
case invalidCharForNumber:
fallthrough
case dotInNumber:
case invalidCharForNumber, dotInNumber:
return iter.readFloat64SlowPath()
}
decimalPlaces++

View File

@ -2,12 +2,22 @@
package jsoniter
import "fmt"
import (
"fmt"
"io"
)
func (iter *Iterator) skipNumber() {
if !iter.trySkipNumber() {
iter.unreadByte()
iter.ReadFloat32()
if iter.Error != nil && iter.Error != io.EOF {
return
}
iter.ReadFloat64()
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = nil
iter.ReadBigFloat()
}
}
}

View File

@ -114,7 +114,7 @@ func Test_overwrite_interface_value_with_nil(t *testing.T) {
err := json.Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
should.NoError(err)
should.Equal(42, (*(wrapper.Payload.(*Payload))).Value)
should.Equal(42, wrapper.Payload.(*Payload).Value)
err = json.Unmarshal([]byte(`{"payload": null}`), &wrapper)
should.NoError(err)
@ -128,7 +128,7 @@ func Test_overwrite_interface_value_with_nil(t *testing.T) {
err = jsoniter.Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
should.Equal(nil, err)
should.Equal(42, (*(wrapper.Payload.(*Payload))).Value)
should.Equal(42, wrapper.Payload.(*Payload).Value)
err = jsoniter.Unmarshal([]byte(`{"payload": null}`), &wrapper)
should.Equal(nil, err)

View File

@ -338,7 +338,7 @@ func describeStruct(ctx *ctx, typ reflect2.Type) *StructDescriptor {
for i := 0; i < structType.NumField(); i++ {
field := structType.Field(i)
tag, hastag := field.Tag().Lookup(ctx.getTagKey())
if ctx.onlyTaggedField && !hastag {
if ctx.onlyTaggedField && !hastag && !field.Anonymous() {
continue
}
tagParts := strings.Split(tag, ",")

View File

@ -64,14 +64,26 @@ func decoderOfMapKey(ctx *ctx, typ reflect2.Type) ValDecoder {
return &numericMapKeyDecoder{decoderOfType(ctx, typ)}
default:
ptrType := reflect2.PtrTo(typ)
if ptrType.Implements(textMarshalerType) {
if ptrType.Implements(unmarshalerType) {
return &referenceDecoder{
&unmarshalerDecoder{
valType: ptrType,
},
}
}
if typ.Implements(unmarshalerType) {
return &unmarshalerDecoder{
valType: typ,
}
}
if ptrType.Implements(textUnmarshalerType) {
return &referenceDecoder{
&textUnmarshalerDecoder{
valType: ptrType,
},
}
}
if typ.Implements(textMarshalerType) {
if typ.Implements(textUnmarshalerType) {
return &textUnmarshalerDecoder{
valType: typ,
}

View File

@ -93,8 +93,7 @@ func (encoder *marshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteNil()
return
}
marshaler := obj.(json.Marshaler)
bytes, err := marshaler.MarshalJSON()
bytes, err := json.Marshal(obj)
if err != nil {
stream.Error = err
} else {

View File

@ -224,3 +224,13 @@ func Test_EmptyInput(t *testing.T) {
t.Errorf("Expected error")
}
}
type Foo struct {
A jsoniter.Any
}
func Test_nil_any(t *testing.T) {
should := require.New(t)
data, _ := jsoniter.Marshal(&Foo{})
should.Equal(`{"A":null}`, string(data))
}

View File

@ -2,7 +2,9 @@ package test
import (
"encoding/json"
"fmt"
"math/big"
"time"
)
func init() {
@ -27,6 +29,8 @@ func init() {
nilMap,
&nilMap,
map[string]*json.RawMessage{"hello": pRawMessage(json.RawMessage("[]"))},
map[Date]bool{{}: true},
map[Date2]bool{{}: true},
)
unmarshalCases = append(unmarshalCases, unmarshalCase{
ptr: (*map[string]string)(nil),
@ -37,6 +41,20 @@ func init() {
}, unmarshalCase{
ptr: (*map[string]*json.RawMessage)(nil),
input: "{\"test\":[{\"key\":\"value\"}]}",
}, unmarshalCase{
ptr: (*map[Date]bool)(nil),
input: `{
"2018-12-12": true,
"2018-12-13": true,
"2018-12-14": true
}`,
}, unmarshalCase{
ptr: (*map[Date2]bool)(nil),
input: `{
"2018-12-12": true,
"2018-12-13": true,
"2018-12-14": true
}`,
})
}
@ -49,3 +67,51 @@ type MyString string
func (ms MyString) Hello() string {
return string(ms)
}
type Date struct {
time.Time
}
func (d *Date) UnmarshalJSON(b []byte) error {
dateStr := string(b) // something like `"2017-08-20"`
if dateStr == "null" {
return nil
}
t, err := time.Parse(`"2006-01-02"`, dateStr)
if err != nil {
return fmt.Errorf("cant parse date: %#v", err)
}
d.Time = t
return nil
}
func (d *Date) MarshalJSON() ([]byte, error) {
return []byte(d.Time.Format("2006-01-02")), nil
}
type Date2 struct {
time.Time
}
func (d Date2) UnmarshalJSON(b []byte) error {
dateStr := string(b) // something like `"2017-08-20"`
if dateStr == "null" {
return nil
}
t, err := time.Parse(`"2006-01-02"`, dateStr)
if err != nil {
return fmt.Errorf("cant parse date: %#v", err)
}
d.Time = t
return nil
}
func (d Date2) MarshalJSON() ([]byte, error) {
return []byte(d.Time.Format("2006-01-02")), nil
}

View File

@ -7,15 +7,18 @@ import (
func init() {
marshalCases = append(marshalCases,
json.RawMessage("{}"),
selectedMarshalCase{struct {
struct {
Env string `json:"env"`
Extra json.RawMessage `json:"extra,omitempty"`
}{
Env: "jfdk",
}},
},
)
unmarshalCases = append(unmarshalCases, unmarshalCase{
ptr: (*json.RawMessage)(nil),
input: `[1,2,3]`,
}, unmarshalCase{
ptr: (*json.RawMessage)(nil),
input: `1.122e+250`,
})
}