package
main
import
(
"encoding/json"
"fmt"
)
func main() {
a := `{
"id"
:
280123412341234123
}`
fmt.Printf(
"a:%v\n"
, a)
para := make(map[string]
interface
{})
err := json.Unmarshal([]
byte
(a), ¶)
fmt.Printf(
"para:%v, err:%v\n"
, para, err)
id := int64(para[
"id"
].(float64))
fmt.Printf(
"id:%v\n"
, id)
}
|
上面的代码会输出
a:{
"id"
:
280123412341234123
}
para:map[id:
2
.801234123412341e+
17
], err:<nil>
id:
280123412341234112
|
可以看到,id的大数字被unmarshal转化成float64类型,从而出现了精度缺失。
json照成精度缺失的源代码:
---------------------encoding/json/decode.go:
case
reflect.Interface:
n, err := d.convertNumber(s)
if
err != nil {
d.saveError(err)
break
}
if
v.NumMethod() !=
0
{
d.saveError(&UnmarshalTypeError{
"number"
, v.Type(), int64(d.off)})
break
}
v.Set(reflect.ValueOf(n))
---------------------encoding/json/decode.go:
// convertNumber converts the number literal s to a float64 or a Number
// depending on the setting of d.useNumber.
func (d *decodeState) convertNumber(s string) (
interface
{}, error) {
if
d.useNumber {
return
Number(s), nil
}
f, err := strconv.ParseFloat(s,
64
)
if
err != nil {
return
nil, &UnmarshalTypeError{
"number "
+ s, reflect.TypeOf(
0.0
), int64(d.off)}
}
return
f, nil
}
|
可以看到,在convertNumber中,如果设置了useNumber将会转化为json.Number这种对象,而不是默认的float64。
解决方法:
使用UseNumber(),注意需要使用decoder,不能直接unmarshal
package
main
import
(
"encoding/json"
"fmt"
"strings"
)
func main() {
a := `{
"id"
:
280123412341234123
}`
fmt.Printf(
"a:%v\n"
, a)
para := make(map[string]
interface
{})
decoder := json.NewDecoder(strings.NewReader(a))
decoder.UseNumber()
err := decoder.Decode(¶)
fmt.Printf(
"para:%v, err:%v\n"
, para, err)
id, err := para[
"id"
].(json.Number).Int64()
fmt.Printf(
"id:%v, err:%v\n"
, id, err)
}
|
输出:
a:{
"id"
:
280123412341234123
}
para:map[id:
280123412341234123
], err:<nil>
id:
280123412341234123
, err:<nil>
|