On Thu, 2 Mar 2017 02:29:22 -0800 (PST)
Basile Starynkevitch <
bas...@starynkevitch.net> wrote:
> I want to JSON encode a float64 point number always as a JSON float,
> so 1.0 should be encoded as 1.0 not as 1 because at decoding time I
> want to distinguish them.
[...]
Use custom type with a custom marshaler [1]:
------------>8------------
package main
import (
"encoding/json"
"fmt"
"math"
"os"
)
type myFloat64 float64
func (mf myFloat64) MarshalJSON() ([]byte, error) {
const ε = 1e-12
v := float64(mf)
w, f := math.Modf(v)
if f < ε {
return []byte(fmt.Sprintf(`%v.0`, math.Trunc(w))), nil
}
return json.Marshal(v)
}
type data struct {
Header *json.RawMessage `json:"header"`
Body string `json:"body"`
Mass myFloat64 `json:"mass"`
}
func main() {
h := json.RawMessage(`{"precomputed": true}`)
for _, item := range []data{
{
Header: &h,
Body: "Hello Gophers!",
Mass: 1.0,
},
{
Header: &h,
Body: "Holã Gophers!",
Mass: 1.42,
},
} {
b, err := json.MarshalIndent(&item, "", "\t")
if err != nil {
fmt.Println("error:", err)
}
os.Stdout.Write(b)
}
}
------------>8------------
Which outputs:
{
"header": {
"precomputed": true
},
"body": "Hello Gophers!",
"mass": 1.0
}{
"header": {
"precomputed": true
},
"body": "Holã Gophers!",
"mass": 1.42
}
I'm not truly sure about the usage of epsilon: maybe it's OK for your
case to just compare the fractional part with float64(0).
1.
https://play.golang.org/p/d9cTkr70sJ