Skip to content

Commit 0329bd6

Browse files
authored
Merge pull request #40 from francoispqt/feature/generator
Feature/generator
2 parents 9f5ebac + c1d7f03 commit 0329bd6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+6648
-20
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ go:
66

77
script:
88
- go get github.com/stretchr/testify
9+
- go test ./gojay -race
910
- go test -race -coverprofile=coverage.txt -covermode=atomic
1011

1112
after_success:

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,17 @@
88
![stability-stable](https://img.shields.io/badge/stability-stable-green.svg)
99

1010
# GoJay
11+
12+
<img src="https://github.com/francoispqt/gojay/raw/feature/generator/gojay.png" width="200px">
13+
1114
GoJay is a performant JSON encoder/decoder for Golang (currently the most performant, [see benchmarks](#benchmark-results)).
1215

1316
It has a simple API and doesn't use reflection. It relies on small interfaces to decode/encode structures and slices.
1417

1518
Gojay also comes with powerful stream decoding features and an even faster [Unsafe](#unsafe-api) API.
1619

20+
There is also a [code generation tool](https://github.com/francoispqt/gojay/tree/master/gojay) to make usage easier and faster.
21+
1722
# Why another JSON parser?
1823

1924
I looked at other fast decoder/encoder and realised it was mostly hardly readable static code generation or a lot of reflection, poor streaming features, and not so fast in the end.
@@ -31,7 +36,7 @@ go get github.com/francoispqt/gojay
3136
* [Encoder](#encoding)
3237
* [Decoder](#decoding)
3338
* [Stream API](#stream-api)
34-
39+
* [Code Generation](https://github.com/francoispqt/gojay/tree/master/gojay)
3540

3641
## Decoding
3742

decode.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,13 @@ func (dec *Decoder) AddUint64(v *uint64) error {
294294
// AddFloat decodes the next key to a *float64.
295295
// If next key value overflows float64, an InvalidUnmarshalError error will be returned.
296296
func (dec *Decoder) AddFloat(v *float64) error {
297-
return dec.Float(v)
297+
return dec.Float64(v)
298+
}
299+
300+
// AddFloat64 decodes the next key to a *float64.
301+
// If next key value overflows float64, an InvalidUnmarshalError error will be returned.
302+
func (dec *Decoder) AddFloat64(v *float64) error {
303+
return dec.Float64(v)
298304
}
299305

300306
// AddFloat32 decodes the next key to a *float64.
@@ -428,6 +434,12 @@ func (dec *Decoder) Uint64(v *uint64) error {
428434
// Float decodes the next key to a *float64.
429435
// If next key value overflows float64, an InvalidUnmarshalError error will be returned.
430436
func (dec *Decoder) Float(v *float64) error {
437+
return dec.Float64(v)
438+
}
439+
440+
// Float64 decodes the next key to a *float64.
441+
// If next key value overflows float64, an InvalidUnmarshalError error will be returned.
442+
func (dec *Decoder) Float64(v *float64) error {
431443
err := dec.decodeFloat64(v)
432444
if err != nil {
433445
return err

decode_array.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,23 @@ func (dec *Decoder) skipArray() (int, error) {
106106
}
107107
return 0, dec.raiseInvalidJSONErr(dec.cursor)
108108
}
109+
110+
// DecodeArrayFunc is a custom func type implementing UnarshaleArray.
111+
// Use it to cast a func(*Decoder) to Unmarshal an object.
112+
//
113+
// str := ""
114+
// dec := gojay.NewDecoder(io.Reader)
115+
// dec.DecodeArray(gojay.DecodeArrayFunc(func(dec *gojay.Decoder, k string) error {
116+
// return dec.AddString(&str)
117+
// }))
118+
type DecodeArrayFunc func(*Decoder) error
119+
120+
// UnmarshalJSONArray implements UnarshalerArray.
121+
func (f DecodeArrayFunc) UnmarshalJSONArray(dec *Decoder) error {
122+
return f(dec)
123+
}
124+
125+
// IsNil implements UnarshalerArray.
126+
func (f DecodeArrayFunc) IsNil() bool {
127+
return f == nil
128+
}

decode_array_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,3 +566,8 @@ func TestDecodeArrayNullError(t *testing.T) {
566566
assert.NotNil(t, err, "err should not be nil")
567567
assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
568568
}
569+
570+
func TestDecoderArrayFunc(t *testing.T) {
571+
var f DecodeArrayFunc
572+
assert.True(t, f.IsNil())
573+
}

decode_number_float_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,3 +630,58 @@ func TestDecoderFloat32(t *testing.T) {
630630
assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
631631
})
632632
}
633+
634+
func TestDecoderFloat64Field(t *testing.T) {
635+
var testCasesBasic = []struct {
636+
name string
637+
json string
638+
value float64
639+
}{
640+
{
641+
name: "basic",
642+
json: "[1]",
643+
value: float64(1),
644+
},
645+
{
646+
name: "big",
647+
json: "[0]",
648+
value: float64(0),
649+
},
650+
}
651+
for _, testCase := range testCasesBasic {
652+
t.Run(testCase.name, func(t *testing.T) {
653+
var dec = NewDecoder(strings.NewReader(testCase.json))
654+
var v float64
655+
dec.DecodeArray(DecodeArrayFunc(func(dec *Decoder) error {
656+
return dec.AddFloat64(&v)
657+
}))
658+
assert.Equal(t, testCase.value, v)
659+
})
660+
}
661+
var testCasesBasicAlt = []struct {
662+
name string
663+
json string
664+
value float64
665+
}{
666+
{
667+
name: "basic",
668+
json: "[1]",
669+
value: float64(1),
670+
},
671+
{
672+
name: "big",
673+
json: "[0]",
674+
value: float64(0),
675+
},
676+
}
677+
for _, testCase := range testCasesBasicAlt {
678+
t.Run(testCase.name, func(t *testing.T) {
679+
var dec = NewDecoder(strings.NewReader(testCase.json))
680+
var v float64
681+
dec.DecodeArray(DecodeArrayFunc(func(dec *Decoder) error {
682+
return dec.Float(&v)
683+
}))
684+
assert.Equal(t, testCase.value, v)
685+
})
686+
}
687+
}

encode_array.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,22 @@ func (enc *Encoder) ArrayKeyOmitEmpty(key string, v MarshalerJSONArray) {
128128
v.MarshalJSONArray(enc)
129129
enc.writeByte(']')
130130
}
131+
132+
// EncodeArrayFunc is a custom func type implementing MarshaleArray.
133+
// Use it to cast a func(*Encoder) to Marshal an object.
134+
//
135+
// enc := gojay.NewEncoder(io.Writer)
136+
// enc.EncodeArray(gojay.EncodeArrayFunc(func(enc *gojay.Encoder) {
137+
// enc.AddStringKey("hello", "world")
138+
// }))
139+
type EncodeArrayFunc func(*Encoder)
140+
141+
// MarshalJSONArray implements MarshalerJSONArray.
142+
func (f EncodeArrayFunc) MarshalJSONArray(enc *Encoder) {
143+
f(enc)
144+
}
145+
146+
// IsNil implements MarshalerJSONArray.
147+
func (f EncodeArrayFunc) IsNil() bool {
148+
return f == nil
149+
}

encode_array_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,3 +331,8 @@ func TestEncoderArrErrors(t *testing.T) {
331331
assert.True(t, false, "should not be called as it should have panicked")
332332
})
333333
}
334+
335+
func TestEncoderArrayFunc(t *testing.T) {
336+
var f EncodeArrayFunc
337+
assert.True(t, f.IsNil())
338+
}

encode_number_float.go

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,61 @@ func (enc *Encoder) encodeFloat32(n float32) ([]byte, error) {
4141

4242
// AddFloat adds a float64 to be encoded, must be used inside a slice or array encoding (does not encode a key)
4343
func (enc *Encoder) AddFloat(v float64) {
44-
enc.Float(v)
44+
enc.Float64(v)
4545
}
4646

4747
// AddFloatOmitEmpty adds a float64 to be encoded and skips it if its value is 0,
4848
// must be used inside a slice or array encoding (does not encode a key).
4949
func (enc *Encoder) AddFloatOmitEmpty(v float64) {
50-
enc.FloatOmitEmpty(v)
50+
enc.Float64OmitEmpty(v)
5151
}
5252

5353
// Float adds a float64 to be encoded, must be used inside a slice or array encoding (does not encode a key)
5454
func (enc *Encoder) Float(v float64) {
55+
enc.Float64(v)
56+
}
57+
58+
// FloatOmitEmpty adds a float64 to be encoded and skips it if its value is 0,
59+
// must be used inside a slice or array encoding (does not encode a key).
60+
func (enc *Encoder) FloatOmitEmpty(v float64) {
61+
enc.Float64OmitEmpty(v)
62+
}
63+
64+
// AddFloatKey adds a float64 to be encoded, must be used inside an object as it will encode a key
65+
func (enc *Encoder) AddFloatKey(key string, v float64) {
66+
enc.Float64Key(key, v)
67+
}
68+
69+
// AddFloatKeyOmitEmpty adds a float64 to be encoded and skips it if its value is 0.
70+
// Must be used inside an object as it will encode a key
71+
func (enc *Encoder) AddFloatKeyOmitEmpty(key string, v float64) {
72+
enc.Float64KeyOmitEmpty(key, v)
73+
}
74+
75+
// FloatKey adds a float64 to be encoded, must be used inside an object as it will encode a key
76+
func (enc *Encoder) FloatKey(key string, v float64) {
77+
enc.Float64Key(key, v)
78+
}
79+
80+
// FloatKeyOmitEmpty adds a float64 to be encoded and skips it if its value is 0.
81+
// Must be used inside an object as it will encode a key
82+
func (enc *Encoder) FloatKeyOmitEmpty(key string, v float64) {
83+
enc.Float64KeyOmitEmpty(key, v)
84+
}
85+
86+
// AddFloat64 adds a float64 to be encoded, must be used inside a slice or array encoding (does not encode a key)
87+
func (enc *Encoder) AddFloat64(v float64) {
88+
enc.Float(v)
89+
}
90+
91+
// AddFloat64OmitEmpty adds a float64 to be encoded and skips it if its value is 0,
92+
// must be used inside a slice or array encoding (does not encode a key).
93+
func (enc *Encoder) AddFloat64OmitEmpty(v float64) {
94+
enc.FloatOmitEmpty(v)
95+
}
96+
97+
// Float64 adds a float64 to be encoded, must be used inside a slice or array encoding (does not encode a key)
98+
func (enc *Encoder) Float64(v float64) {
5599
enc.grow(10)
56100
r := enc.getPreviousRune()
57101
if r != '[' {
@@ -60,9 +104,9 @@ func (enc *Encoder) Float(v float64) {
60104
enc.buf = strconv.AppendFloat(enc.buf, v, 'f', -1, 64)
61105
}
62106

63-
// FloatOmitEmpty adds a float64 to be encoded and skips it if its value is 0,
107+
// Float64OmitEmpty adds a float64 to be encoded and skips it if its value is 0,
64108
// must be used inside a slice or array encoding (does not encode a key).
65-
func (enc *Encoder) FloatOmitEmpty(v float64) {
109+
func (enc *Encoder) Float64OmitEmpty(v float64) {
66110
if v == 0 {
67111
return
68112
}
@@ -74,19 +118,19 @@ func (enc *Encoder) FloatOmitEmpty(v float64) {
74118
enc.buf = strconv.AppendFloat(enc.buf, v, 'f', -1, 64)
75119
}
76120

77-
// AddFloatKey adds a float64 to be encoded, must be used inside an object as it will encode a key
78-
func (enc *Encoder) AddFloatKey(key string, v float64) {
121+
// AddFloat64Key adds a float64 to be encoded, must be used inside an object as it will encode a key
122+
func (enc *Encoder) AddFloat64Key(key string, v float64) {
79123
enc.FloatKey(key, v)
80124
}
81125

82-
// AddFloatKeyOmitEmpty adds a float64 to be encoded and skips it if its value is 0.
126+
// AddFloat64KeyOmitEmpty adds a float64 to be encoded and skips it if its value is 0.
83127
// Must be used inside an object as it will encode a key
84-
func (enc *Encoder) AddFloatKeyOmitEmpty(key string, v float64) {
128+
func (enc *Encoder) AddFloat64KeyOmitEmpty(key string, v float64) {
85129
enc.FloatKeyOmitEmpty(key, v)
86130
}
87131

88-
// FloatKey adds a float64 to be encoded, must be used inside an object as it will encode a key
89-
func (enc *Encoder) FloatKey(key string, value float64) {
132+
// Float64Key adds a float64 to be encoded, must be used inside an object as it will encode a key
133+
func (enc *Encoder) Float64Key(key string, value float64) {
90134
r := enc.getPreviousRune()
91135
if r != '{' {
92136
enc.writeByte(',')
@@ -98,9 +142,9 @@ func (enc *Encoder) FloatKey(key string, value float64) {
98142
enc.buf = strconv.AppendFloat(enc.buf, value, 'f', -1, 64)
99143
}
100144

101-
// FloatKeyOmitEmpty adds a float64 to be encoded and skips it if its value is 0.
145+
// Float64KeyOmitEmpty adds a float64 to be encoded and skips it if its value is 0.
102146
// Must be used inside an object as it will encode a key
103-
func (enc *Encoder) FloatKeyOmitEmpty(key string, v float64) {
147+
func (enc *Encoder) Float64KeyOmitEmpty(key string, v float64) {
104148
if v == 0 {
105149
return
106150
}

0 commit comments

Comments
 (0)