我正在使用golang编组和解组JSON,当我想使用数字字段时,golang会以浮点数转换它,而不是使用长数字。例如。
我有以下JSON:
{
"id": 12423434,
"Name": "Fernando"
}
将marshal
发送到地图并再次unmarshal
发送到json字符串后我得到:
{
"id":1.2423434e+07,
"Name":"Fernando"
}
如您所见,"id"
字段采用浮点表示法。
我使用的代码如下:
package main
import (
"encoding/json"
"fmt"
"os"
)
func main() {
//Create the Json string
var b = []byte(`
{
"id": 12423434,
"Name": "Fernando"
}
`)
//Marshal the json to a map
var f interface{}
json.Unmarshal(b, &f)
m := f.(map[string]interface{})
//print the map
fmt.Println(m)
//unmarshal the map to json
result,_:= json.Marshal(m)
//print the json
os.Stdout.Write(result)
}
打印:
map[id:1.2423434e+07 Name:Fernando]
{"Name":"Fernando","id":1.2423434e+07}
似乎是地图的第一个marshal
生成了FP。我该如何修复它?
这是goland游乐场中程序的链接: http://play.golang.org/p/RRJ6uU4Uw-
答案 0 :(得分:68)
有些时候你不能提前定义一个结构,但仍然需要数字来通过marshal-unmarshal进程不变。
在这种情况下,您可以在UseNumber
上使用json.Decoder
方法,这会导致所有数字解组为json.Number
(这只是数字的原始字符串表示形式)。这对于在JSON中存储非常大的整数也很有用。
例如:
package main
import (
"strings"
"encoding/json"
"fmt"
"log"
)
var data = `{
"id": 12423434,
"Name": "Fernando"
}`
func main() {
d := json.NewDecoder(strings.NewReader(data))
d.UseNumber()
var x interface{}
if err := d.Decode(&x); err != nil {
log.Fatal(err)
}
fmt.Printf("decoded to %#v\n", x)
result, err := json.Marshal(x)
if err != nil {
log.Fatal(err)
}
fmt.Printf("encoded to %s\n", result)
}
<强>结果:强>
decoded to map[string]interface {}{"id":"12423434", "Name":"Fernando"}
encoded to {"Name":"Fernando","id":12423434}
答案 1 :(得分:15)
JSON standard没有长号或浮点数,只有数字。如果您没有定义任何其他内容,则json
包将假定为float64(意思是,仅提供Unmarshal
interface{}
。)
你应该做的是创建一个合适的结构(如Volker所提到的):
package main
import (
"encoding/json"
"fmt"
"os"
)
type Person struct {
Id int64 `json:"id"`
Name string `json:"name"`
}
func main() {
//Create the Json string
var b = []byte(`{"id": 12423434, "Name": "Fernando"}`)
//Marshal the json to a proper struct
var f Person
json.Unmarshal(b, &f)
//print the person
fmt.Println(f)
//unmarshal the struct to json
result, _ := json.Marshal(f)
//print the json
os.Stdout.Write(result)
}
<强>结果:强>
{12423434 Fernando}
{ “ID”:12423434, “姓名”: “费尔南多”}
游乐场:http://play.golang.org/p/2R76DYVgMK
修改强>
如果您有动态json结构并希望使用结构的好处,可以使用json.RawMessage
来解决它。类型json.RawMessage
的变量将存储原始JSON字符串,以便稍后在您知道它包含哪种对象时,可以将其解组为正确的结构。无论您使用何种解决方案,在任何情况下都需要一些if
或switch
语句来确定它的结构类型。
当JSON数据的某些部分只被复制到另一个JSON对象时,例如使用id
- JSON RPC请求的值时,它也很有用。
使用json.RawMessage和相应的JSON数据的容器结构示例:
type Container struct {
Type string `json:"type"`
Data json.RawMessage `json:"data"`
}
var b = []byte(`{"type": "person", "data":{"id": 12423434, "Name": "Fernando"}}`)
Playground上示例的修改版本:http://play.golang.org/p/85s130Sthu
<强> EDIT2:强>
如果您的JSON值的结构基于名称/值对的名称,您可以使用以下内容执行相同操作:
type Container map[string]json.RawMessage