Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions gen/encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@ var primitiveStringEncoders = map[reflect.Kind]string{
reflect.Float64: "out.Float64Str(float64(%v))",
}

var primitiveNoExpEncoders = map[reflect.Kind]string{
reflect.Float32: "out.Float32NoExp(float32(%v))",
reflect.Float64: "out.Float64NoExp(float64(%v))",
}

var primitiveStringNoExpEncoders = map[reflect.Kind]string{
reflect.Float32: "out.Float32StrNoExp(float32(%v))",
reflect.Float64: "out.Float64StrNoExp(float64(%v))",
}

// fieldTags contains parsed version of json struct field tags.
type fieldTags struct {
name string
Expand All @@ -60,6 +70,7 @@ type fieldTags struct {
required bool
intern bool
noCopy bool
noExponent bool
}

// parseFieldTags parses the json field tag into a structure.
Expand All @@ -84,6 +95,8 @@ func parseFieldTags(f reflect.StructField) fieldTags {
ret.intern = true
case s == "nocopy":
ret.noCopy = true
case s == "noexponent":
ret.noExponent = true
}
}

Expand Down Expand Up @@ -129,9 +142,22 @@ func (g *Generator) genTypeEncoderNoCheck(t reflect.Type, in string, tags fieldT
ws := strings.Repeat(" ", indent)

// Check whether type is primitive, needs to be done after interface check.
if enc := primitiveStringEncoders[t.Kind()]; enc != "" && tags.asString {
fmt.Fprintf(g.out, ws+enc+"\n", in)
return nil
// Check tag combinations in priority order
if tags.asString && tags.noExponent {
if enc := primitiveStringNoExpEncoders[t.Kind()]; enc != "" {
fmt.Fprintf(g.out, ws+enc+"\n", in)
return nil
}
} else if tags.asString {
if enc := primitiveStringEncoders[t.Kind()]; enc != "" {
fmt.Fprintf(g.out, ws+enc+"\n", in)
return nil
}
} else if tags.noExponent {
if enc := primitiveNoExpEncoders[t.Kind()]; enc != "" {
fmt.Fprintf(g.out, ws+enc+"\n", in)
return nil
}
}

if enc := primitiveEncoders[t.Kind()]; enc != "" {
Expand Down
40 changes: 40 additions & 0 deletions jwriter/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,46 @@ func (w *Writer) Float64Str(n float64) {
w.Buffer.Buf = append(w.Buffer.Buf, '"')
}

func (w *Writer) Float32NoExp(n float32) {
if w.checkIsUnsupportedFloat(float64(n)) {
return
}

w.Buffer.EnsureSpace(20)
w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, float64(n), 'f', -1, 32)
}

func (w *Writer) Float32StrNoExp(n float32) {
if w.checkIsUnsupportedFloat(float64(n)) {
return
}

w.Buffer.EnsureSpace(22)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, float64(n), 'f', -1, 32)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
}

func (w *Writer) Float64NoExp(n float64) {
if w.checkIsUnsupportedFloat(n) {
return
}

w.Buffer.EnsureSpace(20)
w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, n, 'f', -1, 64)
}

func (w *Writer) Float64StrNoExp(n float64) {
if w.checkIsUnsupportedFloat(n) {
return
}

w.Buffer.EnsureSpace(22)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, n, 'f', -1, 64)
w.Buffer.Buf = append(w.Buffer.Buf, '"')
}

func (w *Writer) Bool(v bool) {
w.Buffer.EnsureSpace(5)
if v {
Expand Down
1 change: 1 addition & 0 deletions tests/basic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ var testCases = []struct {
{&myTypeDeclaredValue, myTypeDeclaredString},
{&myTypeNotSkippedValue, myTypeNotSkippedString},
{&intern, internString},
{&noExpStruct, noExpString},
}

func TestMarshal(t *testing.T) {
Expand Down
20 changes: 20 additions & 0 deletions tests/noexponent.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package tests

//easyjson:json
type NoExponentStruct struct {
Scientific float64 `json:"sci"`
NoExp float64 `json:"price,noexponent"`
Mixed float64 `json:"rate,omitempty,noexponent"`
QuotedNoExp float64 `json:"str,string,noexponent"`
Float32Test float32 `json:"f32,noexponent"`
}

var noExpStruct = NoExponentStruct{
Scientific: 100000000,
NoExp: 100000000,
Mixed: 0.000001,
QuotedNoExp: 1234.5678,
Float32Test: 999.999,
}

var noExpString = `{"sci":1e+08,"price":100000000,"rate":0.000001,"str":"1234.5678","f32":999.999}`
43 changes: 43 additions & 0 deletions tests/noexponent_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package tests

import (
"testing"
)

func TestNoExponentMarshal(t *testing.T) {
data, err := noExpStruct.MarshalJSON()
if err != nil {
t.Errorf("MarshalJSON() error: %v", err)
return
}

got := string(data)
if got != noExpString {
t.Errorf("MarshalJSON() = %v, want %v", got, noExpString)
}
}

func TestNoExponentUnmarshal(t *testing.T) {
var got NoExponentStruct
err := got.UnmarshalJSON([]byte(noExpString))
if err != nil {
t.Errorf("UnmarshalJSON() error: %v", err)
return
}

if got.Scientific != noExpStruct.Scientific {
t.Errorf("Scientific = %v, want %v", got.Scientific, noExpStruct.Scientific)
}
if got.NoExp != noExpStruct.NoExp {
t.Errorf("NoExp = %v, want %v", got.NoExp, noExpStruct.NoExp)
}
if got.Mixed != noExpStruct.Mixed {
t.Errorf("Mixed = %v, want %v", got.Mixed, noExpStruct.Mixed)
}
if got.QuotedNoExp != noExpStruct.QuotedNoExp {
t.Errorf("QuotedNoExp = %v, want %v", got.QuotedNoExp, noExpStruct.QuotedNoExp)
}
if got.Float32Test != noExpStruct.Float32Test {
t.Errorf("Float32Test = %v, want %v", got.Float32Test, noExpStruct.Float32Test)
}
}