Published: 31 August 2021, 18:00
JSON states for “JavaScript Object Notation”. It’s a subset of JavaScript and representation of values is based on how they are represented in JavaScript:
import json
json.dumps(1) # '1'
json.dumps(1.2) # '1.2'
json.dumps('hi') # '"hi"'
json.dumps({}) # '{}'
json.dumps([]) # '[]'
json.dumps(None) # 'null'
json.dumps(float('inf')) # 'Infinity'
json.dumps(float('nan')) # 'NaN'
The last two examples are valid JavaScript but explicitly forbidden by RFC 4627 “The application/json Media Type for JSON”:
Numeric values that cannot be represented as sequences of digits (such as Infinity and NaN) are not permitted.
And so, the inf
/ nan
values, successfully serialized in Python, can fail deserialization in another language. For example, in Go:
import "encoding/json"
func main() {
var v float64
err := json.Unmarshal(`Infinity`, &v)
println(err)
// Output: invalid character 'I' looking for beginning of value
}
To prevent producing invalid JSON, pass allow_nan=False
argument:
json.dumps(float('nan'), allow_nan=False)
# ValueError: Out of range float values are not JSON compliant