Preserving Data Types in JSON Parsing
One challenge encountered when parsing JSON data in Golang is the automatic conversion of numeric values to floats. This can lead to inconsistencies with the original data, especially when dealing with integer values.
To address this issue, there are several techniques to preserve data types during JSON parsing.
Custom JSON Values
One approach is to utilize the custom JSON value mechanism provided by Go. This involves creating a custom type that implements the json.Marshaler and json.Unmarshaler interfaces. By overriding the MarshalJSON and UnmarshalJSON methods, you can control how numeric values are handled during serialization and deserialization.
Go json.Number
Another option is to use the json.Number type introduced in Go 1.8. By default, numeric values in JSON are parsed as float64. However, by using json.Number and calling the Int64 or Float64 methods, you can explicitly convert the number to an integer or floating-point value, respectively.
Example Implementation
package main import ( "encoding/json" "fmt" "strconv" "strings" ) type MyJSONNumber struct { json.Number } func (mn *MyJSONNumber) MarshalJSON() ([]byte, error) { if n, err := strconv.Atoi(string(mn.Number)); err == nil { return []byte(strconv.Itoa(n)), nil } return []byte(mn.Number), nil } func (mn *MyJSONNumber) UnmarshalJSON(b []byte) error { if n, err := strconv.Atoi(string(b)); err == nil { mn.Number = strconv.Itoa(n) return nil } mn.Number = string(b) return nil } 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) jnum := MyJSONNumber{json.Number(s)} n, err := jnum.Int64() if err == nil { parsed[key] = n continue } f, err := jnum.Float64() 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
The above is the detailed content of How Can I Preserve Data Types When Parsing JSON in Go?. For more information, please follow other related articles on the PHP Chinese website!