JSON Marshaling avec de longs nombres dans Golang, donne un nombre à virgule flottante

J’étais en train de marshaler un JSON non-amortissant en utilisant golang et quand je veux le faire avec des champs numériques, golang le transforme en nombres à virgule flottante au lieu d’utiliser des nombres longs, par exemple.

J’ai le JSON suivant:

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

Après l’avoir rassemblé sur une carte et unmarshal à nouveau sur une chaîne json, j’obtiens:

 { "id":1.2423434e+07, "Name":"Fernando" } 

Comme vous pouvez le voir, le champ “id” est en notation à virgule flottante.

Le code que j’utilise est le suivant:

 package main import ( "encoding/json" "fmt" "os" ) func main() { //Create the Json ssortingng var b = []byte(` { "id": 12423434, "Name": "Fernando" } `) //Marshal the json to a map var f interface{} json.Unmarshal(b, &f) m := f.(map[ssortingng]interface{}) //print the map fmt.Println(m) //unmarshal the map to json result,_:= json.Marshal(m) //print the json os.Stdout.Write(result) } 

Il affiche: map [id: 1.2423434e + 07 Nom: Fernando] {“Nom”: “Fernando”, “id”: 1.2423434e + 07}

Il semble que le premier marshal de la carte génère le FP. Comment puis-je le réparer longtemps?

Ceci est le lien vers le programme dans le jeu de golf: http://play.golang.org/p/RRJ6uU4Uw-

Fer

Il y a des moments où vous ne pouvez pas définir une structure à l’avance, mais vous devez toujours passer les nombres au processus marshal-unmarshal sans les modifier.

Dans ce cas, vous pouvez utiliser la méthode UseNumber sur json.Decoder, qui provoque la suppression de tous les nombres en tant que json.Number (qui correspond uniquement à la représentation sous forme de chaîne du numéro). Cela peut également être utile pour stocker de très gros entiers en JSON.

Par exemple:

 package main import ( "ssortingngs" "encoding/json" "fmt" "log" ) var data = `{ "id": 12423434, "Name": "Fernando" }` func main() { d := json.NewDecoder(ssortingngs.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) } 

Résultat:

 decoded to map[ssortingng]interface {}{"id":"12423434", "Name":"Fernando"} encoded to {"Name":"Fernando","id":12423434} 

Le standard JSON n’a pas de longs ni de flottants, il ne contient que des nombres. Le paquetage json supposera float64 lorsque vous n’avez pas défini d’autre chose (ce qui signifie qu’il n’a fourni à Unmarshal qu’une interface{} ).

Ce que vous devez faire est de créer une structure appropriée (comme Volker l’a mentionné):

 package main import ( "encoding/json" "fmt" "os" ) type Person struct { Id int64 `json:"id"` Name ssortingng `json:"name"` } func main() { //Create the Json ssortingng 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) } 

Résultat:

{12423434 Fernando}
{“id”: 12423434, “name”: “Fernando”}

Terrain de jeu: http://play.golang.org/p/2R76DYVgMK

Modifier:

Si vous avez une structure json dynamic et souhaitez utiliser les avantages d’une structure, vous pouvez la résoudre en utilisant json.RawMessage . Une variable de type json.RawMessage stockera la chaîne JSON brute afin que, plus tard, lorsque vous saurez quel type d’object il contient, vous pourrez le supprimer dans la structure appropriée. Quelle que soit la solution que vous utilisez, vous aurez en tout cas besoin d’une instruction if ou switch pour déterminer le type de structure.

Cela est également utile lorsque des parties des données JSON ne seront copiées que dans un autre object JSON, par exemple avec la valeur id d’une requête RPC JSON.

Exemple de structure de conteneur utilisant json.RawMessage et les données JSON correspondantes:

 type Container struct { Type ssortingng `json:"type"` Data json.RawMessage `json:"data"` } var b = []byte(`{"type": "person", "data":{"id": 12423434, "Name": "Fernando"}}`) 

Une version modifiée de votre exemple sur Playground: http://play.golang.org/p/85s130Sthu

Edit2:

Si la structure de votre valeur JSON est basée sur le nom d’une paire nom / valeur, vous pouvez faire la même chose avec:

 type Container map[ssortingng]json.RawMessage