JSON数字在解组为接口后被截断。

huangapple go评论78阅读模式
英文:

JSON number gets cut off after unmarshaling to interface

问题

所以我有一个包含许多字段的JSON,我按照https://stackoverflow.com/questions/66893640/how-effectively-to-change-json-keys中的建议进行循环遍历,以删除我不需要的一些键。但是在删除之后,现有JSON的原始值发生了变化,其中一些似乎是浮点数,我制作了一个演示来展示这一点。

我该如何改变这种行为?是interface{}引起了这个问题吗?为什么1684366653200744506被截断为1684366653200744400

谢谢!

https://go.dev/play/p/X2auWqWB2fL

供参考,输出的JSON已更改为1684366653200744400

2009/11/10 23:00:00 1684366653200744448.000000
2009/11/10 23:00:00 map[timestamp:1.6843666532007444e+18]
2009/11/10 23:00:00 json Marshal from maps of key string and value interface to batch json for insert to DB
2009/11/10 23:00:00 {"timestamp":1684366653200744400}
英文:

So I have a JSON with many fields and I am looping through it as suggested by
https://stackoverflow.com/questions/66893640/how-effectively-to-change-json-keys
to delete some of the keys I don't need. But after deletion, the original values of the existing JSON was changed, some of them are float numbers it seems and I made a demo to show it.

How can I change this behavior? Is the interface{} causing the issue? Why is 1684366653200744506 cut off to 1684366653200744400?

Thanks!

https://go.dev/play/p/X2auWqWB2fL

For reference, the output JSON is changed to 1684366653200744400

2009/11/10 23:00:00 1684366653200744448.000000
2009/11/10 23:00:00 map[timestamp:1.6843666532007444e+18]
2009/11/10 23:00:00 json Marshal from maps of key string and value interface to batch json for insert to DB
2009/11/10 23:00:00 {"timestamp":1684366653200744400}

答案1

得分: 2

我建议创建一个类型并删除你不需要的字段。

package main

import (
	"encoding/json"
	"log"
)

type A struct {
	Timestamp int64 `json:"timestamp"`
}

func main() {
	jsonBatch := `{"timestamp":1684366653200744506, "todelete":"string value or boolean value"}`
	i := A{}
	if err := json.Unmarshal([]byte(jsonBatch), &i); err != nil {
		log.Println("从批处理JSON解组失败")
		log.Println(err)
	}
	dbJsonBatch, err := json.Marshal(i)
	if err != nil {
		log.Println("将键为字符串和值为接口的映射组合成批处理JSON以插入到数据库中失败")
		log.Println(err)
	}
	log.Println("将键为字符串和值为接口的映射组合成批处理JSON以插入到数据库中")
	log.Println(string(dbJsonBatch))
}

这将打印:

2009/11/10 23:00:00 将键为字符串和值为接口的映射组合成批处理JSON以插入到数据库中
2009/11/10 23:00:00 {"timestamp":1684366653200744506}
英文:

I suggest creating a type and removing the field you don't need.

package main

import (
	"encoding/json"
	"log"
)

type A struct {
	Timestamp int64 `json:"timestamp"`
}

func main() {
	jsonBatch := `{"timestamp":1684366653200744506, "todelete":"string value or boolean value"}`
	i := A{}
	if err := json.Unmarshal([]byte(jsonBatch), &i); err != nil {
		log.Println("json UnMarshal from batch json failed")
		log.Println(err)
	}
	dbJsonBatch, err := json.Marshal(i)
	if err != nil {
		log.Println("json Marshal from batch json failed")
		log.Println(err)
	}
	log.Println("json Marshal from maps of key string and value interface to batch json for insert to DB")
	log.Println(string(dbJsonBatch))
}

This prints

2009/11/10 23:00:00 json Marshal from maps of key string and value interface to batch json for insert to DB
2009/11/10 23:00:00 {"timestamp":1684366653200744506}

答案2

得分: 2

这是因为默认情况下,encoding/json 包将 JSON 数字存储为接口值中的 float64 类型。可以参考 json.Unmarshal

> 为了将 JSON 解组成接口值,Unmarshal 将以下类型之一存储在接口值中:
> - 布尔值,用于 JSON 布尔值
> - float64,用于 JSON 数字
> - ...

你可以创建一个解码器并调用 (*Decoder).UseNumber 来改变这种行为:

jsonBatch := `{"timestamp":1684366653200744506, "todelete":"string value or boolean value"}`
dec := json.NewDecoder(strings.NewReader(jsonBatch))
dec.UseNumber()
var i interface{}
if err := dec.Decode(&i); err != nil {

参考链接:https://go.dev/play/p/ZjWB-NfiEQL。

英文:

It's because by default, the encoding/json package stores float64 in the interface value for JSON numbers. See json.Unmarshal:

> To unmarshal JSON into an interface value, Unmarshal stores one of these in the interface value:
> - bool, for JSON booleans
> - float64, for JSON numbers
> - ...

You can create a decoder and call (*Decoder).UseNumber to change the behavior:

jsonBatch := `{"timestamp":1684366653200744506, "todelete":"string value or boolean value"}`
dec := json.NewDecoder(strings.NewReader(jsonBatch))
dec.UseNumber()
var i interface{}
if err := dec.Decode(&i); err != nil {

See https://go.dev/play/p/ZjWB-NfiEQL.

huangapple
  • 本文由 发表于 2023年5月18日 08:01:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76276905.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定