2014-03-12 39 views
35

我正在編組使用golang的反編組JSON,當我想用​​數字字段進行編組時,golang會將其轉換爲浮點數而不是使用長整數。JSON使用Golang中的長數字編碼給出浮點數

我有以下的JSON:

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

它元帥到地圖後,並解組再次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) 

} 

它打印: 地圖。[ID:1.2423434e + 07產品名:費爾南多] { 「名稱」: 「費爾南多」, 「ID」 :1.2423434e + 07}

看起來,地圖的第一個元帥會生成FP。我如何解決它很長?

這是在操場的Goland的鏈接程序: http://play.golang.org/p/RRJ6uU4Uw-

費爾

+2

不要編組到一個'映射[字符串]接口{}'但用適當的結構例如'id'的'int64'字段。 – Volker

回答

9

JSON standard沒有多頭或浮動,它只有數字。當你還沒有定義其他任何東西時(意味着,只提供Unmarshalinterface{}),json包將假定爲float64。

你應該做的是創造一個合適的結構(如沃爾克提到的):

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費爾南多}
{ 「ID」:12423434, 「name」:「Fernando」}

遊樂場:http://play.golang.org/p/2R76DYVgMK

編輯:

如果你有一個動態的JSON結構,並希望使用結構的好處,你可以使用json.RawMessage解決這個問題。類型爲json.RawMessage的變量將存儲原始JSON字符串,以便稍後當您知道其包含的對象類型時,可以將其解組爲合適的結構。無論您使用什麼解決方案,在任何情況下都需要一些ifswitch聲明,您可以在其中確定它是哪種類型的結構。

當JSON數據的一部分只會被複制到另一個JSON對象時,如使用JSON RPC請求的id值時,它也很有用。

使用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"}}`) 

你的例子的上游樂場的修改後的版本:http://play.golang.org/p/85s130Sthu

EDIT2:

如果您的JSON值的結構是基於的名稱名稱/值對,你可以用同樣的方法:

type Container map[string]json.RawMessage 
+0

評論「/ /統帥json到地圖」應該已被更改爲「/ /編組json到結構」。 – peterSO

+0

@peterSo:我剛注意到我錯過了評論。修復它「結構」 – ANisus

+1

問題y我存儲不同的json結構,所以我不知道哪個會是de結構在閱讀json之前 – Fersca

50

有時候你不能定義一個結構,但仍然需要數字通過元帥解組過程不變。

在這種情況下,您可以在json.Decoder上使用UseNumber方法,這會導致所有數字解組爲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

不錯!那就是我一直在尋找的東西,我會嘗試使用它並提供反饋。 – Fersca

+0

太好了,我擔心真正的浮動也會被轉換爲整數。幸運的是它沒有:https://play.golang.org/p/TRo0v4yeBO – linqu

+1

@Fersca這似乎是答案;如果你還在身邊,也許接受它? –