[series] go – JSON Small pit encountered by unmarshal

Time:2022-1-7

1. Description of problem phenomenon

usejson.Unmarshal(), during deserialization, the scientific counting method appears, and the reference code is as follows:

jsonStr := `{"number":1234567}`
result := make(map[string]interface{})
err := json.Unmarshal([]byte(jsonStr), &result)
if err != nil {
	fmt.Println(err)
}
fmt.Println(result)

//Output
// map[number:1.234567e+06]

This problem is not inevitable. Only when the number of digits is greater than 6, it will become a scientific counting method.

2. Problem impact description

When the data structure is unknown, usemap[string]interface{}When receiving deserialization results, if the number of digits is greater than 6, it will become a scientific counting method, and the places used will be affected.

3. Causes of problems

fromencoding/jsonYou can find the answer. Take a look at this note:

// To unmarshal JSON into an interface value,
// Unmarshal stores one of these in the interface value:
//
//	bool, for JSON booleans
//	float64, for JSON numbers
//	string, for JSON strings
//	[]interface{}, for JSON arrays
//	map[string]interface{}, for JSON objects
//	nil for JSON null

Because whenJSONWhen there is a large number in, it will be parsed intofloat64Type, there may be the form of scientific counting.

4. Solutions to problems

Scheme I

Cast type, reference code is as follows:

jsonStr := `{"number":1234567}`
result := make(map[string]interface{})
err := json.Unmarshal([]byte(jsonStr), &result)
if err != nil {
	fmt.Println(err)
}
fmt.Println(int(result["number"].(float64)))

//Output
// 1234567

Scheme II

Try to avoid usinginterfaceYesjsonThe string structure defines the structure. The shortcut method can use the online tool:https://mholt.github.io/json-to-go/

type Num struct {
	Number int `json:"number"`
}

jsonStr := `{"number":1234567}`
var result Num
err := json.Unmarshal([]byte(jsonStr), &result)
if err != nil {
	fmt.Println(err)
}
fmt.Println(result)

//Output
// {1234567}

Programme III

useUseNumber()method.

jsonStr := `{"number":1234567}`
result := make(map[string]interface{})
d := json.NewDecoder(bytes.NewReader([]byte(jsonStr)))
d.UseNumber()
err := d.Decode(&result)
if err != nil {
	fmt.Println(err)
}
fmt.Println(result)

//Output
// map[number:1234567]

Be careful at this timeresult["number"]Data type!

fmt.Println(fmt.Sprintf("type: %v", reflect.TypeOf(result["number"])))

//Output
// type: json.Number

As can be seen from the codejson.NumberIt’s actually a string type:

// A Number represents a JSON number literal.
type Number string

If converting other types, refer to the following code:

//Convert to Int64
numInt, _ := result["number"].(json.Number).Int64()
fmt.Println(fmt.Sprintf("value: %v, type: %v", numInt, reflect.TypeOf(numInt)))

//Output
// value: 1234567, type: int64

//Convert to string
numStr := result["number"].(json.Number).String()
fmt.Println(fmt.Sprintf("value: %v, type: %v", numStr, reflect.TypeOf(numStr)))

//Output
// value: 1234567, type: string

Recommended Today

Tutorial on sending e-mail using net:: SMTP class in Ruby

Simple Mail Transfer Protocol(SMTP)SendE-mailAnd routing protocol processing between e-mail servers. RubyIt provides the connection of simple mail transfer protocol (SMTP) client of net:: SMTP class, and provides two new methods: new and start New takes two parameters: Server name defaults to localhost Port number defaults to 25 The start method takes these parameters: Server – […]