francoispqt / gojay

high performance JSON encoder/decoder with stream API for Golang
MIT License
2.11k stars 112 forks source link

How should I handle NaN in floating numbers? #123

Closed noamt closed 4 years ago

noamt commented 5 years ago

If I have a struct with a floating point number field like:

type A struct {
    B float64
}

func (a *A) MarshalJSONObject(enc *gojay.Encoder) {
    enc.Float64Key("b", a.B)
}

func (a *A) IsNil() bool {
    return a == nil
}

And I assign it with NaN like:

a := &A{B: math.NaN()}

Running this through the standard library's Marshal method will fail with Error: json: unsupported value: NaN:

_, e := json.Marshal(a)
fmt.Println("Error:", e)

But using GoJay's Marshal method produces an invalid JSON {"b":NaN}:

b, e := gojay.Marshal(a)
fmt.Println(string(b))

How would you recommend handling this situation?

marcsantiago commented 4 years ago

Consider checking if the value is NaN within the marshaller

e.g

package main

import (
    "encoding/json"
    "fmt"
    "math"

    "github.com/francoispqt/gojay"
)

type A struct {
    B float64
}

func (a *A) MarshalJSONObject(enc *gojay.Encoder) {
    if !math.IsNaN(a.B) {
        enc.Float64Key("b", a.B)
    }

}

func (a *A) IsNil() bool {
    return a == nil
}

func main() {
    a := &A{B: math.NaN()}
    b, e := json.Marshal(a)
    fmt.Printf("body %s Error: %v\n", b, e)

    b, e = gojay.Marshal(a)
    fmt.Printf("body %s Error: %v\n", b, e)
}

https://goplay.space/#2CR0VbuT-M0

It won't error out still, but the JSON will be a valid empty JSON