diff --git a/cmd/jsontoml/main.go b/cmd/jsontoml/main.go index d65f5ab9..5a1fbe4a 100644 --- a/cmd/jsontoml/main.go +++ b/cmd/jsontoml/main.go @@ -45,7 +45,6 @@ func convert(r io.Reader, w io.Writer) error { var v interface{} d := json.NewDecoder(r) - d.UseNumber() err := d.Decode(&v) if err != nil { return err diff --git a/cmd/jsontoml/main_test.go b/cmd/jsontoml/main_test.go index 022b89c2..4a4ad072 100644 --- a/cmd/jsontoml/main_test.go +++ b/cmd/jsontoml/main_test.go @@ -25,7 +25,7 @@ func TestConvert(t *testing.T) { } }`, expected: `[mytoml] -a = 42 +a = 42.0 `, }, { diff --git a/marshaler.go b/marshaler.go index ffa18a5f..8be595f2 100644 --- a/marshaler.go +++ b/marshaler.go @@ -42,6 +42,7 @@ type Encoder struct { arraysMultiline bool indentSymbol string indentTables bool + jsonNumber bool } // NewEncoder returns a new Encoder that writes to w. @@ -88,6 +89,13 @@ func (enc *Encoder) SetIndentTables(indent bool) *Encoder { return enc } +// SetJsonNumber forces the encoder to serialize `json.Number` as a float or integer +// instead of relying on TextMarshaler to emit a string. +func (enc *Encoder) SetJsonNumber(indent bool) *Encoder { + enc.jsonNumber = indent + return enc +} + // Encode writes a TOML representation of v to the stream. // // If v cannot be represented to TOML it returns an error. @@ -254,14 +262,16 @@ func (enc *Encoder) encode(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, e case LocalDateTime: return append(b, x.String()...), nil case json.Number: - if x == "" { /// Useful zero value. - return append(b, "0"...), nil - } else if v, err := x.Int64(); err == nil { - return enc.encode(b, ctx, reflect.ValueOf(v)) - } else if f, err := x.Float64(); err == nil { - return enc.encode(b, ctx, reflect.ValueOf(f)) - } else { - return nil, fmt.Errorf("toml: unable to convert %q to int64 or float64", x) + if enc.jsonNumber { + if x == "" { /// Useful zero value. + return append(b, "0"...), nil + } else if v, err := x.Int64(); err == nil { + return enc.encode(b, ctx, reflect.ValueOf(v)) + } else if f, err := x.Float64(); err == nil { + return enc.encode(b, ctx, reflect.ValueOf(f)) + } else { + return nil, fmt.Errorf("toml: unable to convert %q to int64 or float64", x) + } } } diff --git a/marshaler_test.go b/marshaler_test.go index c179b126..deb1b7bd 100644 --- a/marshaler_test.go +++ b/marshaler_test.go @@ -679,31 +679,6 @@ I = 42 J = 42 K = 42 L = 2.2 -`, - }, - { - desc: "json numbers", - v: struct { - A json.Number - B json.Number - C json.Number - D json.Number - E json.Number - F json.Number - }{ - A: "1.1", - B: "42e-3", - C: "42", - D: "0", - E: "0.0", - F: "", - }, - expected: `A = 1.1 -B = 0.042 -C = 42 -D = 0 -E = 0.0 -F = 0 `, }, { @@ -973,6 +948,29 @@ func TestEncoderSetIndentSymbol(t *testing.T) { assert.Equal(t, expected, w.String()) } +func TestEncoderSetJsonNumber(t *testing.T) { + var w strings.Builder + enc := toml.NewEncoder(&w) + enc.SetJsonNumber(true) + err := enc.Encode(map[string]interface{}{ + "A": json.Number("1.1"), + "B": json.Number("42e-3"), + "C": json.Number("42"), + "D": json.Number("0"), + "E": json.Number("0.0"), + "F": json.Number(""), + }) + require.NoError(t, err) + expected := `A = 1.1 +B = 0.042 +C = 42 +D = 0 +E = 0.0 +F = 0 +` + assert.Equal(t, expected, w.String()) +} + func TestEncoderOmitempty(t *testing.T) { type doc struct { String string `toml:",omitempty,multiline"`