私は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-
構造体を事前に定義できない場合でも、マーシャリングとアンマーシャリングのプロセスを変更せずに渡すために数値が必要な場合があります。
その場合、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}
JSON標準 にはlongやfloatはなく、数字のみがあります。 json
パッケージは、他に何も定義していない場合にfloat64を想定します(つまり、interface{}
でUnmarshal
のみを提供します)。
あなたがすべきことは、適切な構造体を作成することです(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フェルナンド}
{"id":12423434、 "name": "Fernando"}
遊び場: http://play.golang.org/p/2R76DYVgMK
編集:
動的なjson構造があり、構造の利点を使用したい場合は、json.RawMessage
を使用して解決できます。タイプjson.RawMessage
の変数は生のJSON文字列を保存するため、後でどの種類のオブジェクトが含まれているかがわかったときに、適切な構造体にマーシャリング解除できます。どのソリューションを使用する場合でも、どのタイプの構造であるかを決定するif
またはswitch
ステートメントが必要になります。
JSON RPCリクエストのid
- valueなどを使用して、JSONデータの一部を別のJSONオブジェクトにのみコピーする場合にも役立ちます。
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/85s130Sth
Edit2:
JSON値の構造が名前と値のペアの名前に基づいている場合、次の方法で同じことができます。
type Container map[string]json.RawMessage