You've already forked json-iterator
mirror of
https://github.com/json-iterator/go.git
synced 2025-06-15 22:50:24 +02:00
Compare commits
20 Commits
Author | SHA1 | Date | |
---|---|---|---|
0ff49de124 | |||
5bc9320502 | |||
f64ce68b6e | |||
2d42ff74dd | |||
3a023a5fbc | |||
16aef10b2b | |||
ae4c002f78 | |||
e4aa2ec063 | |||
d05f387f50 | |||
a9403d25cd | |||
05d041de10 | |||
5916df66b3 | |||
2433035e51 | |||
6dfc0bf2dd | |||
b9be8dd373 | |||
b8d78b6aaf | |||
7109b5e7dd | |||
4cc76529e8 | |||
c5ddac9dc3 | |||
f76d712086 |
@ -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)
|
You can also use thrift like JSON using [thrift-iterator](https://github.com/thrift-iterator/go)
|
||||||
|
|
||||||
```
|
|
||||||
Go开发者们请加入我们,滴滴出行平台技术部 taowen@didichuxing.com
|
|
||||||
```
|
|
||||||
|
|
||||||
# Benchmark
|
# Benchmark
|
||||||
|
|
||||||

|

|
||||||
|
4
any.go
4
any.go
@ -312,6 +312,10 @@ func (codec *directAnyCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
|||||||
|
|
||||||
func (codec *directAnyCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
func (codec *directAnyCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||||
any := *(*Any)(ptr)
|
any := *(*Any)(ptr)
|
||||||
|
if any == nil {
|
||||||
|
stream.WriteNil()
|
||||||
|
return
|
||||||
|
}
|
||||||
any.WriteTo(stream)
|
any.WriteTo(stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,10 +82,8 @@ func Test_read_float_to_any(t *testing.T) {
|
|||||||
should := require.New(t)
|
should := require.New(t)
|
||||||
any := jsoniter.WrapFloat64(12.3)
|
any := jsoniter.WrapFloat64(12.3)
|
||||||
anyFloat64 := float64(12.3)
|
anyFloat64 := float64(12.3)
|
||||||
//negaAnyFloat64 := float64(-1.1)
|
|
||||||
any2 := jsoniter.WrapFloat64(-1.1)
|
any2 := jsoniter.WrapFloat64(-1.1)
|
||||||
should.Equal(float64(12.3), any.ToFloat64())
|
should.Equal(float64(12.3), any.ToFloat64())
|
||||||
//should.Equal("12.3", any.ToString())
|
|
||||||
should.True(any.ToBool())
|
should.True(any.ToBool())
|
||||||
should.Equal(float32(anyFloat64), any.ToFloat32())
|
should.Equal(float32(anyFloat64), any.ToFloat32())
|
||||||
should.Equal(int(anyFloat64), any.ToInt())
|
should.Equal(int(anyFloat64), any.ToInt())
|
||||||
|
@ -118,6 +118,4 @@ func Test_object_wrapper_any_get_all(t *testing.T) {
|
|||||||
should.Contains(any.Keys(), "Field1")
|
should.Contains(any.Keys(), "Field1")
|
||||||
should.Contains(any.Keys(), "Field2")
|
should.Contains(any.Keys(), "Field2")
|
||||||
should.NotContains(any.Keys(), "Field3")
|
should.NotContains(any.Keys(), "Field3")
|
||||||
|
|
||||||
//should.Contains(any.GetObject()["Field1"].GetArray()[0], 1)
|
|
||||||
}
|
}
|
||||||
|
@ -172,3 +172,58 @@ func Test_CaseSensitive_MoreThanTenFields(t *testing.T) {
|
|||||||
should.Equal(tc.expectedOutput, output)
|
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)
|
||||||
|
}
|
||||||
|
36
api_tests/marshal_json_test.go
Normal file
36
api_tests/marshal_json_test.go
Normal 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())
|
||||||
|
}
|
@ -95,7 +95,7 @@ func ExampleGet() {
|
|||||||
// Crimson
|
// Crimson
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleMapKey() {
|
func ExampleMyKey() {
|
||||||
hello := MyKey("hello")
|
hello := MyKey("hello")
|
||||||
output, _ := Marshal(map[*MyKey]string{&hello: "world"})
|
output, _ := Marshal(map[*MyKey]string{&hello: "world"})
|
||||||
fmt.Println(string(output))
|
fmt.Println(string(output))
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
package test
|
package test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"github.com/json-iterator/go"
|
"github.com/json-iterator/go"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
"bytes"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_customize_type_decoder(t *testing.T) {
|
func Test_customize_type_decoder(t *testing.T) {
|
||||||
|
@ -153,7 +153,7 @@ func (codec *binaryAsStringCodec) Decode(ptr unsafe.Pointer, iter *jsoniter.Iter
|
|||||||
}
|
}
|
||||||
b4 := rawBytes[i+3]
|
b4 := rawBytes[i+3]
|
||||||
b5 := rawBytes[i+4]
|
b5 := rawBytes[i+4]
|
||||||
i = i + 4
|
i += 4
|
||||||
b = readHex(iter, b4, b5)
|
b = readHex(iter, b4, b5)
|
||||||
}
|
}
|
||||||
bytes = append(bytes, b)
|
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}))
|
iter.ReportError("read hex", "expects 0~9 or a~f, but found "+string([]byte{b1}))
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
ret = ret * 16
|
ret *= 16
|
||||||
if b2 >= '0' && b2 <= '9' {
|
if b2 >= '0' && b2 <= '9' {
|
||||||
ret = b2 - '0'
|
ret = b2 - '0'
|
||||||
} else if b2 >= 'a' && b2 <= 'f' {
|
} else if b2 >= 'a' && b2 <= 'f' {
|
||||||
|
@ -77,14 +77,12 @@ func (iter *Iterator) ReadFloat32() (ret float32) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (iter *Iterator) readPositiveFloat32() (ret float32) {
|
func (iter *Iterator) readPositiveFloat32() (ret float32) {
|
||||||
value := uint64(0)
|
|
||||||
c := byte(' ')
|
|
||||||
i := iter.head
|
i := iter.head
|
||||||
// first char
|
// first char
|
||||||
if i == iter.tail {
|
if i == iter.tail {
|
||||||
return iter.readFloat32SlowPath()
|
return iter.readFloat32SlowPath()
|
||||||
}
|
}
|
||||||
c = iter.buf[i]
|
c := iter.buf[i]
|
||||||
i++
|
i++
|
||||||
ind := floatDigits[c]
|
ind := floatDigits[c]
|
||||||
switch ind {
|
switch ind {
|
||||||
@ -107,7 +105,7 @@ func (iter *Iterator) readPositiveFloat32() (ret float32) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
value = uint64(ind)
|
value := uint64(ind)
|
||||||
// chars before dot
|
// chars before dot
|
||||||
non_decimal_loop:
|
non_decimal_loop:
|
||||||
for ; i < iter.tail; i++ {
|
for ; i < iter.tail; i++ {
|
||||||
@ -145,9 +143,7 @@ non_decimal_loop:
|
|||||||
}
|
}
|
||||||
// too many decimal places
|
// too many decimal places
|
||||||
return iter.readFloat32SlowPath()
|
return iter.readFloat32SlowPath()
|
||||||
case invalidCharForNumber:
|
case invalidCharForNumber, dotInNumber:
|
||||||
fallthrough
|
|
||||||
case dotInNumber:
|
|
||||||
return iter.readFloat32SlowPath()
|
return iter.readFloat32SlowPath()
|
||||||
}
|
}
|
||||||
decimalPlaces++
|
decimalPlaces++
|
||||||
@ -218,14 +214,12 @@ func (iter *Iterator) ReadFloat64() (ret float64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (iter *Iterator) readPositiveFloat64() (ret float64) {
|
func (iter *Iterator) readPositiveFloat64() (ret float64) {
|
||||||
value := uint64(0)
|
|
||||||
c := byte(' ')
|
|
||||||
i := iter.head
|
i := iter.head
|
||||||
// first char
|
// first char
|
||||||
if i == iter.tail {
|
if i == iter.tail {
|
||||||
return iter.readFloat64SlowPath()
|
return iter.readFloat64SlowPath()
|
||||||
}
|
}
|
||||||
c = iter.buf[i]
|
c := iter.buf[i]
|
||||||
i++
|
i++
|
||||||
ind := floatDigits[c]
|
ind := floatDigits[c]
|
||||||
switch ind {
|
switch ind {
|
||||||
@ -248,7 +242,7 @@ func (iter *Iterator) readPositiveFloat64() (ret float64) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
value = uint64(ind)
|
value := uint64(ind)
|
||||||
// chars before dot
|
// chars before dot
|
||||||
non_decimal_loop:
|
non_decimal_loop:
|
||||||
for ; i < iter.tail; i++ {
|
for ; i < iter.tail; i++ {
|
||||||
@ -286,9 +280,7 @@ non_decimal_loop:
|
|||||||
}
|
}
|
||||||
// too many decimal places
|
// too many decimal places
|
||||||
return iter.readFloat64SlowPath()
|
return iter.readFloat64SlowPath()
|
||||||
case invalidCharForNumber:
|
case invalidCharForNumber, dotInNumber:
|
||||||
fallthrough
|
|
||||||
case dotInNumber:
|
|
||||||
return iter.readFloat64SlowPath()
|
return iter.readFloat64SlowPath()
|
||||||
}
|
}
|
||||||
decimalPlaces++
|
decimalPlaces++
|
||||||
|
@ -2,12 +2,22 @@
|
|||||||
|
|
||||||
package jsoniter
|
package jsoniter
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
func (iter *Iterator) skipNumber() {
|
func (iter *Iterator) skipNumber() {
|
||||||
if !iter.trySkipNumber() {
|
if !iter.trySkipNumber() {
|
||||||
iter.unreadByte()
|
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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ func Test_overwrite_interface_value_with_nil(t *testing.T) {
|
|||||||
|
|
||||||
err := json.Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
|
err := json.Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
|
||||||
should.NoError(err)
|
should.NoError(err)
|
||||||
should.Equal(42, (*(wrapper.Payload.(*Payload))).Value)
|
should.Equal(42, wrapper.Payload.(*Payload).Value)
|
||||||
|
|
||||||
err = json.Unmarshal([]byte(`{"payload": null}`), &wrapper)
|
err = json.Unmarshal([]byte(`{"payload": null}`), &wrapper)
|
||||||
should.NoError(err)
|
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)
|
err = jsoniter.Unmarshal([]byte(`{"payload": {"val": 42}}`), &wrapper)
|
||||||
should.Equal(nil, err)
|
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)
|
err = jsoniter.Unmarshal([]byte(`{"payload": null}`), &wrapper)
|
||||||
should.Equal(nil, err)
|
should.Equal(nil, err)
|
||||||
|
@ -338,7 +338,7 @@ func describeStruct(ctx *ctx, typ reflect2.Type) *StructDescriptor {
|
|||||||
for i := 0; i < structType.NumField(); i++ {
|
for i := 0; i < structType.NumField(); i++ {
|
||||||
field := structType.Field(i)
|
field := structType.Field(i)
|
||||||
tag, hastag := field.Tag().Lookup(ctx.getTagKey())
|
tag, hastag := field.Tag().Lookup(ctx.getTagKey())
|
||||||
if ctx.onlyTaggedField && !hastag {
|
if ctx.onlyTaggedField && !hastag && !field.Anonymous() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
tagParts := strings.Split(tag, ",")
|
tagParts := strings.Split(tag, ",")
|
||||||
|
@ -64,14 +64,26 @@ func decoderOfMapKey(ctx *ctx, typ reflect2.Type) ValDecoder {
|
|||||||
return &numericMapKeyDecoder{decoderOfType(ctx, typ)}
|
return &numericMapKeyDecoder{decoderOfType(ctx, typ)}
|
||||||
default:
|
default:
|
||||||
ptrType := reflect2.PtrTo(typ)
|
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{
|
return &referenceDecoder{
|
||||||
&textUnmarshalerDecoder{
|
&textUnmarshalerDecoder{
|
||||||
valType: ptrType,
|
valType: ptrType,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if typ.Implements(textMarshalerType) {
|
if typ.Implements(textUnmarshalerType) {
|
||||||
return &textUnmarshalerDecoder{
|
return &textUnmarshalerDecoder{
|
||||||
valType: typ,
|
valType: typ,
|
||||||
}
|
}
|
||||||
|
@ -93,8 +93,7 @@ func (encoder *marshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
|||||||
stream.WriteNil()
|
stream.WriteNil()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
marshaler := obj.(json.Marshaler)
|
bytes, err := json.Marshal(obj)
|
||||||
bytes, err := marshaler.MarshalJSON()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
stream.Error = err
|
stream.Error = err
|
||||||
} else {
|
} else {
|
||||||
|
@ -224,3 +224,13 @@ func Test_EmptyInput(t *testing.T) {
|
|||||||
t.Errorf("Expected error")
|
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))
|
||||||
|
}
|
||||||
|
@ -2,7 +2,9 @@ package test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -27,6 +29,8 @@ func init() {
|
|||||||
nilMap,
|
nilMap,
|
||||||
&nilMap,
|
&nilMap,
|
||||||
map[string]*json.RawMessage{"hello": pRawMessage(json.RawMessage("[]"))},
|
map[string]*json.RawMessage{"hello": pRawMessage(json.RawMessage("[]"))},
|
||||||
|
map[Date]bool{{}: true},
|
||||||
|
map[Date2]bool{{}: true},
|
||||||
)
|
)
|
||||||
unmarshalCases = append(unmarshalCases, unmarshalCase{
|
unmarshalCases = append(unmarshalCases, unmarshalCase{
|
||||||
ptr: (*map[string]string)(nil),
|
ptr: (*map[string]string)(nil),
|
||||||
@ -37,6 +41,20 @@ func init() {
|
|||||||
}, unmarshalCase{
|
}, unmarshalCase{
|
||||||
ptr: (*map[string]*json.RawMessage)(nil),
|
ptr: (*map[string]*json.RawMessage)(nil),
|
||||||
input: "{\"test\":[{\"key\":\"value\"}]}",
|
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 {
|
func (ms MyString) Hello() string {
|
||||||
return string(ms)
|
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
|
||||||
|
}
|
||||||
|
@ -7,15 +7,18 @@ import (
|
|||||||
func init() {
|
func init() {
|
||||||
marshalCases = append(marshalCases,
|
marshalCases = append(marshalCases,
|
||||||
json.RawMessage("{}"),
|
json.RawMessage("{}"),
|
||||||
selectedMarshalCase{struct {
|
struct {
|
||||||
Env string `json:"env"`
|
Env string `json:"env"`
|
||||||
Extra json.RawMessage `json:"extra,omitempty"`
|
Extra json.RawMessage `json:"extra,omitempty"`
|
||||||
}{
|
}{
|
||||||
Env: "jfdk",
|
Env: "jfdk",
|
||||||
}},
|
},
|
||||||
)
|
)
|
||||||
unmarshalCases = append(unmarshalCases, unmarshalCase{
|
unmarshalCases = append(unmarshalCases, unmarshalCase{
|
||||||
ptr: (*json.RawMessage)(nil),
|
ptr: (*json.RawMessage)(nil),
|
||||||
input: `[1,2,3]`,
|
input: `[1,2,3]`,
|
||||||
|
}, unmarshalCase{
|
||||||
|
ptr: (*json.RawMessage)(nil),
|
||||||
|
input: `1.122e+250`,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user