I was marshaling and unmarshaling JSONs using golang and when I want to do it with number fields golang transforms it in floating point numbers instead of use long numbers, for example.
I have the following JSON:
{
"id": 12423434,
"Name": "Fernando"
}
After marshal
it to a map and unmarshal
again to a json string I get:
{
"id":1.2423434e+07,
"Name":"Fernando"
}
As you can see the "id"
field is in floating point notation.
The code that I am using is the following:
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)
}
It prints:
map[id:1.2423434e+07 Name:Fernando]
{"Name":"Fernando","id":1.2423434e+07}
It appears to be that the first marshal
to the map generates the FP. How can I fix it to a long?
This is the link to the program in the goland playground: http://play.golang.org/p/RRJ6uU4Uw-
The JSON standard doesn't have longs or floats, it only has numbers. The
json
package will assume float64 when you haven't defined anything else (meaning, only providedUnmarshal
with aninterface{}
).What you should do is to create a proper struct (as Volker mentioned):
Result:
Playground: http://play.golang.org/p/2R76DYVgMK
Edit:
In case you have a dynamic json structure and wish to use the benefits of a struct, you can solve it using
json.RawMessage
. A variable of typejson.RawMessage
will store the raw JSON string so that you later on, when you know what kind of object it contains, can unmarshal it into the proper struct. No matter what solution you use, you will in any case need someif
orswitch
statement where you determine what type of structure it is.It is also useful when parts of the JSON data will only be copied to the another JSON object such as with the
id
-value of a JSON RPC request.Example of container struct using json.RawMessage and the corresponding JSON data:
A modified version of your example on Playground: http://play.golang.org/p/85s130Sthu
Edit2:
If the structure of your JSON value is based on the name of a name/value pair, you can do the same with a:
There are times when you cannot define a struct in advance but still require numbers to pass through the marshal-unmarshal process unchanged.
In that case you can use the
UseNumber
method onjson.Decoder
, which causes all numbers to unmarshal asjson.Number
(which is just the original string representation of the number). This can also useful for storing very big integers in JSON.For example:
Result: