add UnmarshalJSON function and corresponding unit test cases for package gtype

This commit is contained in:
John
2019-09-29 20:12:59 +08:00
parent 47e74d27bf
commit bb6fed3dc2
18 changed files with 311 additions and 104 deletions

View File

@ -7,6 +7,8 @@
package gtype
import (
"bytes"
"github.com/gogf/gf/util/gconv"
"sync/atomic"
)
@ -14,6 +16,11 @@ type Bool struct {
value int32
}
var (
bytesTrue = []byte("true")
bytesFalse = []byte("false")
)
// NewBool returns a concurrent-safe object for bool type,
// with given initial value <value>.
func NewBool(value ...bool) *Bool {
@ -63,8 +70,14 @@ func (v *Bool) Cas(old, new bool) bool {
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
func (v *Bool) MarshalJSON() ([]byte, error) {
if v.Val() {
return []byte("true"), nil
return bytesTrue, nil
} else {
return []byte("false"), nil
return bytesFalse, nil
}
}
// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal.
func (v *Bool) UnmarshalJSON(b []byte) error {
v.Set(gconv.Bool(bytes.Trim(b, `"`)))
return nil
}

View File

@ -56,3 +56,9 @@ func (v *Byte) Cas(old, new byte) bool {
func (v *Byte) MarshalJSON() ([]byte, error) {
return gconv.UnsafeStrToBytes(strconv.FormatUint(uint64(v.Val()), 10)), nil
}
// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal.
func (v *Byte) UnmarshalJSON(b []byte) error {
v.Set(gconv.Uint8(gconv.UnsafeBytesToStr(b)))
return nil
}

View File

@ -7,6 +7,7 @@
package gtype
import (
"bytes"
"encoding/base64"
"github.com/gogf/gf/util/gconv"
"sync/atomic"
@ -54,3 +55,14 @@ func (v *Bytes) MarshalJSON() ([]byte, error) {
base64.StdEncoding.Encode(dst, val)
return gconv.UnsafeStrToBytes(`"` + gconv.UnsafeBytesToStr(dst) + `"`), nil
}
// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal.
func (v *Bytes) UnmarshalJSON(b []byte) error {
src := make([]byte, base64.StdEncoding.DecodedLen(len(b)))
n, err := base64.StdEncoding.Decode(src, bytes.Trim(b, `"`))
if err != nil {
return nil
}
v.Set(src[:n])
return nil
}

View File

@ -62,10 +62,16 @@ func (v *Float32) Add(delta float32) (new float32) {
// Cas executes the compare-and-swap operation for value.
func (v *Float32) Cas(old, new float32) bool {
return atomic.CompareAndSwapUint32(&v.value, uint32(old), uint32(new))
return atomic.CompareAndSwapUint32(&v.value, math.Float32bits(old), math.Float32bits(new))
}
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
func (v *Float32) MarshalJSON() ([]byte, error) {
return gconv.UnsafeStrToBytes(strconv.FormatFloat(float64(v.Val()), 'f', -1, 32)), nil
return gconv.UnsafeStrToBytes(strconv.FormatFloat(float64(v.Val()), 'g', -1, 32)), nil
}
// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal.
func (v *Float32) UnmarshalJSON(b []byte) error {
v.Set(gconv.Float32(gconv.UnsafeBytesToStr(b)))
return nil
}

View File

@ -62,10 +62,16 @@ func (v *Float64) Add(delta float64) (new float64) {
// Cas executes the compare-and-swap operation for value.
func (v *Float64) Cas(old, new float64) bool {
return atomic.CompareAndSwapUint64(&v.value, uint64(old), uint64(new))
return atomic.CompareAndSwapUint64(&v.value, math.Float64bits(old), math.Float64bits(new))
}
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
func (v *Float64) MarshalJSON() ([]byte, error) {
return gconv.UnsafeStrToBytes(strconv.FormatFloat(v.Val(), 'f', -1, 64)), nil
return gconv.UnsafeStrToBytes(strconv.FormatFloat(v.Val(), 'g', -1, 64)), nil
}
// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal.
func (v *Float64) UnmarshalJSON(b []byte) error {
v.Set(gconv.Float64(gconv.UnsafeBytesToStr(b)))
return nil
}

View File

@ -56,3 +56,9 @@ func (v *Int) Cas(old, new int) bool {
func (v *Int) MarshalJSON() ([]byte, error) {
return gconv.UnsafeStrToBytes(strconv.Itoa(v.Val())), nil
}
// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal.
func (v *Int) UnmarshalJSON(b []byte) error {
v.Set(gconv.Int(gconv.UnsafeBytesToStr(b)))
return nil
}

View File

@ -56,3 +56,9 @@ func (v *Int32) Cas(old, new int32) bool {
func (v *Int32) MarshalJSON() ([]byte, error) {
return gconv.UnsafeStrToBytes(strconv.Itoa(int(v.Val()))), nil
}
// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal.
func (v *Int32) UnmarshalJSON(b []byte) error {
v.Set(gconv.Int32(gconv.UnsafeBytesToStr(b)))
return nil
}

View File

@ -56,3 +56,9 @@ func (v *Int64) Cas(old, new int64) bool {
func (v *Int64) MarshalJSON() ([]byte, error) {
return gconv.UnsafeStrToBytes(strconv.FormatInt(v.Val(), 10)), nil
}
// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal.
func (v *Int64) UnmarshalJSON(b []byte) error {
v.Set(gconv.Int64(gconv.UnsafeBytesToStr(b)))
return nil
}

View File

@ -47,3 +47,14 @@ func (v *Interface) Val() interface{} {
func (v *Interface) MarshalJSON() ([]byte, error) {
return json.Marshal(v.Val())
}
// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal.
func (v *Interface) UnmarshalJSON(b []byte) error {
var i interface{}
err := json.Unmarshal(b, &i)
if err != nil {
return err
}
v.Set(i)
return nil
}

View File

@ -7,6 +7,7 @@
package gtype
import (
"bytes"
"github.com/gogf/gf/util/gconv"
"sync/atomic"
)
@ -50,3 +51,9 @@ func (v *String) Val() string {
func (v *String) MarshalJSON() ([]byte, error) {
return gconv.UnsafeStrToBytes(`"` + v.Val() + `"`), nil
}
// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal.
func (v *String) UnmarshalJSON(b []byte) error {
v.Set(gconv.UnsafeBytesToStr(bytes.Trim(b, `"`)))
return nil
}

View File

@ -56,3 +56,9 @@ func (v *Uint) Cas(old, new uint) bool {
func (v *Uint) MarshalJSON() ([]byte, error) {
return gconv.UnsafeStrToBytes(strconv.FormatUint(uint64(v.Val()), 10)), nil
}
// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal.
func (v *Uint) UnmarshalJSON(b []byte) error {
v.Set(gconv.Uint(gconv.UnsafeBytesToStr(b)))
return nil
}

View File

@ -56,3 +56,9 @@ func (v *Uint32) Cas(old, new uint32) bool {
func (v *Uint32) MarshalJSON() ([]byte, error) {
return gconv.UnsafeStrToBytes(strconv.FormatUint(uint64(v.Val()), 10)), nil
}
// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal.
func (v *Uint32) UnmarshalJSON(b []byte) error {
v.Set(gconv.Uint32(gconv.UnsafeBytesToStr(b)))
return nil
}

View File

@ -56,3 +56,9 @@ func (v *Uint64) Cas(old, new uint64) bool {
func (v *Uint64) MarshalJSON() ([]byte, error) {
return gconv.UnsafeStrToBytes(strconv.FormatUint(v.Val(), 10)), nil
}
// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal.
func (v *Uint64) UnmarshalJSON(b []byte) error {
v.Set(gconv.Uint64(gconv.UnsafeBytesToStr(b)))
return nil
}

View File

@ -6,9 +6,10 @@
// go test *.go -bench=".*" -benchmem
package gtype
package gtype_test
import (
"github.com/gogf/gf/container/gtype"
"strconv"
"sync/atomic"
"testing"
@ -17,17 +18,17 @@ import (
)
var (
it = NewInt()
it32 = NewInt32()
it64 = NewInt64()
uit = NewUint()
uit32 = NewUint32()
uit64 = NewUint64()
bl = NewBool()
bytes = NewBytes()
str = NewString()
inf = NewInterface()
at = atomic.Value{}
it = gtype.NewInt()
it32 = gtype.NewInt32()
it64 = gtype.NewInt64()
uit = gtype.NewUint()
uit32 = gtype.NewUint32()
uit64 = gtype.NewUint64()
bl = gtype.NewBool()
vbytes = gtype.NewBytes()
str = gtype.NewString()
inf = gtype.NewInterface()
at = atomic.Value{}
)
func BenchmarkInt_Set(b *testing.B) {
@ -164,13 +165,13 @@ func BenchmarkString_Val(b *testing.B) {
func BenchmarkBytes_Set(b *testing.B) {
for i := 0; i < b.N; i++ {
bytes.Set(gbinary.EncodeInt(i))
vbytes.Set(gbinary.EncodeInt(i))
}
}
func BenchmarkBytes_Val(b *testing.B) {
for i := 0; i < b.N; i++ {
bytes.Val()
vbytes.Val()
}
}

View File

@ -8,6 +8,7 @@ package gtype_test
import (
"encoding/json"
"math"
"sync"
"testing"
@ -37,6 +38,7 @@ func Test_Bool(t *testing.T) {
gtest.AssertEQ(i2.Val(), false)
})
// Marshal
gtest.Case(t, func() {
i := gtype.NewBool(true)
b1, err1 := json.Marshal(i)
@ -45,7 +47,6 @@ func Test_Bool(t *testing.T) {
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
})
gtest.Case(t, func() {
i := gtype.NewBool(false)
b1, err1 := json.Marshal(i)
@ -54,6 +55,50 @@ func Test_Bool(t *testing.T) {
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
})
// Unmarshal
gtest.Case(t, func() {
var err error
i := gtype.NewBool()
err = json.Unmarshal([]byte("true"), &i)
gtest.Assert(err, nil)
gtest.Assert(i.Val(), true)
err = json.Unmarshal([]byte("false"), &i)
gtest.Assert(err, nil)
gtest.Assert(i.Val(), false)
err = json.Unmarshal([]byte("1"), &i)
gtest.Assert(err, nil)
gtest.Assert(i.Val(), true)
err = json.Unmarshal([]byte("0"), &i)
gtest.Assert(err, nil)
gtest.Assert(i.Val(), false)
})
gtest.Case(t, func() {
i := gtype.NewBool(true)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
i2 := gtype.NewBool()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), i.Val())
})
gtest.Case(t, func() {
i := gtype.NewBool(false)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
i2 := gtype.NewBool()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), i.Val())
})
}
func Test_Byte(t *testing.T) {
@ -79,13 +124,21 @@ func Test_Byte(t *testing.T) {
gtest.AssertEQ(i1.Val(), byte(0))
})
gtest.Case(t, func() {
i := gtype.NewByte(254)
i := gtype.NewByte(49)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
})
// Unmarshal
gtest.Case(t, func() {
var err error
i := gtype.NewByte()
err = json.Unmarshal([]byte("49"), &i)
gtest.Assert(err, nil)
gtest.Assert(i.Val(), "49")
})
}
func Test_Bytes(t *testing.T) {
@ -100,12 +153,18 @@ func Test_Bytes(t *testing.T) {
gtest.AssertEQ(i1.Val(), nil)
})
gtest.Case(t, func() {
i := gtype.NewBytes([]byte("i love gf"))
b := []byte("i love gf")
i := gtype.NewBytes(b)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
i2 := gtype.NewBytes()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), b)
})
}
@ -121,12 +180,18 @@ func Test_String(t *testing.T) {
gtest.AssertEQ(i1.Val(), "")
})
gtest.Case(t, func() {
i := gtype.NewString("i love gf")
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
s := "i love gf"
i1 := gtype.NewString(s)
b1, err1 := json.Marshal(i1)
b2, err2 := json.Marshal(i1.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
i2 := gtype.NewString()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), s)
})
}
@ -144,12 +209,18 @@ func Test_Interface(t *testing.T) {
gtest.AssertEQ(i1.Val(), nil)
})
gtest.Case(t, func() {
i := gtype.New("i love gf")
s := "i love gf"
i := gtype.New(s)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
i2 := gtype.New()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), s)
})
}
@ -177,12 +248,19 @@ func Test_Float32(t *testing.T) {
gtest.AssertEQ(i1.Val(), float32(0))
})
gtest.Case(t, func() {
i := gtype.NewFloat32(3.333)
v := float32(math.MaxFloat32)
i := gtype.NewFloat32(v)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
i2 := gtype.NewFloat32()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), v)
})
}
@ -210,12 +288,18 @@ func Test_Float64(t *testing.T) {
gtest.AssertEQ(i1.Val(), float64(0))
})
gtest.Case(t, func() {
i := gtype.NewFloat64(3.333)
v := math.MaxFloat64
i := gtype.NewFloat64(v)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
i2 := gtype.NewFloat64()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), v)
})
}
@ -242,12 +326,18 @@ func Test_Int(t *testing.T) {
gtest.AssertEQ(i1.Val(), 0)
})
gtest.Case(t, func() {
i := gtype.NewInt(666)
v := 666
i := gtype.NewInt(v)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
i2 := gtype.NewInt()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), v)
})
}
@ -274,12 +364,18 @@ func Test_Int32(t *testing.T) {
gtest.AssertEQ(i1.Val(), int32(0))
})
gtest.Case(t, func() {
i := gtype.NewInt32(666)
v := int32(math.MaxInt32)
i := gtype.NewInt32(v)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
i2 := gtype.NewInt32()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), v)
})
}
@ -306,12 +402,17 @@ func Test_Int64(t *testing.T) {
gtest.AssertEQ(i1.Val(), int64(0))
})
gtest.Case(t, func() {
i := gtype.NewInt64(666)
i := gtype.NewInt64(math.MaxInt64)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
i2 := gtype.NewInt64()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), i)
})
}
@ -344,6 +445,11 @@ func Test_Uint(t *testing.T) {
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
i2 := gtype.NewUint()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), i)
})
}
@ -370,12 +476,17 @@ func Test_Uint32(t *testing.T) {
gtest.AssertEQ(i1.Val(), uint32(0))
})
gtest.Case(t, func() {
i := gtype.NewUint32(666)
i := gtype.NewUint32(math.MaxUint32)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
i2 := gtype.NewUint32()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), i)
})
}
@ -402,11 +513,16 @@ func Test_Uint64(t *testing.T) {
gtest.AssertEQ(i1.Val(), uint64(0))
})
gtest.Case(t, func() {
i := gtype.NewUint64(666)
i := gtype.NewUint64(math.MaxUint64)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
i2 := gtype.NewUint64()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), i)
})
}