diff --git a/gen/encoder.go b/gen/encoder.go index ed6d6ad..ca791bc 100644 --- a/gen/encoder.go +++ b/gen/encoder.go @@ -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 @@ -60,6 +70,7 @@ type fieldTags struct { required bool intern bool noCopy bool + noExponent bool } // parseFieldTags parses the json field tag into a structure. @@ -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 } } @@ -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 != "" { diff --git a/jwriter/writer.go b/jwriter/writer.go index 432bade..4de9afe 100644 --- a/jwriter/writer.go +++ b/jwriter/writer.go @@ -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 { diff --git a/tests/basic_test.go b/tests/basic_test.go index 5bf93f1..81b04f6 100644 --- a/tests/basic_test.go +++ b/tests/basic_test.go @@ -59,6 +59,7 @@ var testCases = []struct { {&myTypeDeclaredValue, myTypeDeclaredString}, {&myTypeNotSkippedValue, myTypeNotSkippedString}, {&intern, internString}, + {&noExpStruct, noExpString}, } func TestMarshal(t *testing.T) { diff --git a/tests/noexponent.go b/tests/noexponent.go new file mode 100644 index 0000000..0d75b33 --- /dev/null +++ b/tests/noexponent.go @@ -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}` diff --git a/tests/noexponent_test.go b/tests/noexponent_test.go new file mode 100644 index 0000000..a96cc52 --- /dev/null +++ b/tests/noexponent_test.go @@ -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) + } +}