在Golang中使用长数字的JSON Marshaling给出了浮点数

Fer*_*sca 51 floating-point json marshalling go

我正在使用golang编组一个解组JSON,当我想用​​数字字段进行编码时,golang会以浮点数转换它,而不是使用长数字.

我有以下JSON:

{
    "id": 12423434, 
    "Name": "Fernando"
}
Run Code Online (Sandbox Code Playgroud)

将它封送到地图并再次解组为json字符串后,我得到:

{
    "id":1.2423434e+07,
    "Name":"Fernando"
}
Run Code Online (Sandbox Code Playgroud)

如您所见,"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)

}
Run Code Online (Sandbox Code Playgroud)

它打印:map [id:1.2423434e + 07姓名:Fernando] {"姓名":"Fernando","id":1.2423434e + 07}

似乎地图的第一个元帅会产生FP.我该如何修复它?

这是goland游乐场的节目链接:http://play.golang.org/p/RRJ6uU4Uw-

费尔

rog*_*rog 72

有些时候你不能提前定义一个结构,但仍然需要数字来通过marshal-unmarshal进程不变.

在这种情况下,您可以使用UseNumberon方法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)
}
Run Code Online (Sandbox Code Playgroud)

结果:

decoded to map[string]interface {}{"id":"12423434", "Name":"Fernando"}
encoded to {"Name":"Fernando","id":12423434}
Run Code Online (Sandbox Code Playgroud)

  • @Fersca这似乎是答案; 如果你还在附近,也许接受它? (3认同)
  • 太好了!这就是我想要的,我会尝试使用它并提供反馈. (2认同)

ANi*_*sus 15

JSON标准没有多头或浮动,它只有数字.在json当你还没有定义任何东西(这意味着,只提供封装将承担float64 Unmarshalinterface{}).

你应该做的是创建一个合适的结构(如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)
}
Run Code Online (Sandbox Code Playgroud)

结果:

{12423434 Fernando}
{"id":12423434,"name":"Fernando"}

游乐场:http://play.golang.org/p/2R76DYVgMK

编辑:

如果您有动态json结构并希望使用结构的好处,您可以使用它来解决它json.RawMessage.类型的变量json.RawMessage将存储原始JSON字符串,以便稍后在您知道它包含哪种对象时,可以将其解组为正确的结构.无论您使用何种解决方案,在任何情况下都需要一些ifswitch声明来确定它的结构类型.

当部分JSON数据仅复制到另一个JSON对象(例如使用idJSON RPC请求的-value)时,它也很有用.

使用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"}}`)
Run Code Online (Sandbox Code Playgroud)

您在Playground上的示例的修改版本:http://play.golang.org/p/85s130Sthu

EDIT2:

如果JSON值的结构基于名称/值对的名称,则可以使用以下命令执行相同操作:

type Container map[string]json.RawMessage
Run Code Online (Sandbox Code Playgroud)