Parsing Integers as Integers and Floats as Floats in JSON Using Golang
In a Golang application that receives a stream of JSON records for forwarding to a data store (InfluxDB), it's crucial to preserve the original data type of integer and float values to avoid type conflicts and ensure successful write operations. While the Ruby JSON parser effortlessly performs this task, the encoding/json package in Golang initially parses all numbers as floats, potentially leading to type mismatch and write failures.
A Workaround Using Custom JSON Values
To replicate the behavior of the Ruby JSON parser, one approach is to utilize the generic Go mechanism for custom JSON values. In this method, JSON numbers are represented as byte arrays (json.RawMessage) and parsed using strconv.ParseInt and strconv.ParseFloat. This allows for accurate conversion of integers and floats:
import ( "encoding/json" "fmt" "strconv" ) func main() { str := `{"a":123,"b":12.3,"c":"123","d":"12.3","e":true}` var raw map[string]json.RawMessage err := json.Unmarshal([]byte(str), &raw) if err != nil { panic(err) } parsed := make(map[string]interface{}, len(raw)) for key, val := range raw { s := string(val) i, err := strconv.ParseInt(s, 10, 64) if err == nil { parsed[key] = i continue } f, err := strconv.ParseFloat(s, 64) if err == nil { parsed[key] = f continue } var v interface{} err = json.Unmarshal(val, &v) if err == nil { parsed[key] = v continue } parsed[key] = val } for key, val := range parsed { fmt.Printf("%T: %v %v\n", val, key, val) } }
Output:
int64: a 123 float64: b 12.3 string: c 123 string: d 12.3 bool: e true
Using the json.Number Type
An alternative approach involves using the Go json.Number type, which allows for efficient parsing of both integers and floats directly from the JSON data:
import ( "encoding/json" "fmt" "strings" ) func main() { str := `{"a":123,"b":12.3,"c":"123","d":"12.3","e":true}` var parsed map[string]interface{} d := json.NewDecoder(strings.NewReader(str)) d.UseNumber() err := d.Decode(&parsed) if err != nil { panic(err) } for key, val := range parsed { n, ok := val.(json.Number) if !ok { continue } if i, err := n.Int64(); err == nil { parsed[key] = i continue } if f, err := n.Float64(); err == nil { parsed[key] = f continue } } for key, val := range parsed { fmt.Printf("%T: %v %v\n", val, key, val) } }
Output:
int64: a 123 float64: b 12.3 string: c 123 string: d 12.3 bool: e true
These methods provide effective solutions for preserving the original data type of integers and floats during JSON parsing in Golang, ensuring accurate and reliable data handling.
The above is the detailed content of How Can I Parse Integers and Floats Accurately from JSON in Golang?. For more information, please follow other related articles on the PHP Chinese website!