When I make an HTTP call to a REST API I may get the JSON value count back as a Number or String. I'ld like to marshal it to be an integer in either case. How can I deal with this in Go?.
Use the "string" field tag option to specify that strings should be converted to numbers. The documentation for the option is:
The "string" option signals that a field is stored as JSON inside a JSON-encoded string. It applies only to fields of string, floating point, integer, or boolean types. This extra level of encoding is sometimes used when communicating with JavaScript programs:
Here's an example use:
type S struct {
Count int `json:"count,string"`
}
playground example
If the JSON value can be number or string, then unmarshal to interface{} and convert to int after unmarshaling:
Count interface{} `json:"count,string"`
Use this function to convert the interface{} value to an int:
func getInt(v interface{}) (int, error) {
switch v := v.(type) {
case float64:
return int(v), nil
case string:
c, err := strconv.Atoi(v)
if err != nil {
return 0, err
}
return c, nil
default:
return 0, fmt.Errorf("conversion to int from %T not supported", v)
}
}
go standard lib "json/encoding" offers a json.Number type for parsing both string number and integers in JSON data.
Here's an example use:
type Foo struct {
Value json.Number `json:"value"`
}
json.Number is actually an alias for string, json.Unmarshal handles it specially during unmarshalling to support both formats, like "123" and 123.
Once you have a json.Number, you can extract its numerical representation using the methods .Int64() or .Float64() according to the need.
playground example:
package main
import (
"encoding/json"
"fmt"
)
type Foo struct {
Value json.Number `json:"value"`
}
func main() {
// json int -> json.Number
var foo Foo
if err := json.Unmarshal([]byte(`{"value": 123}`), &foo); err != nil {
fmt.Println("json unmarshal err:", err)
return
}
fmt.Printf("foo: %+v\n", foo)
// json string -> json.Number
var foo2 Foo
if err := json.Unmarshal([]byte(`{"value": "123"}`), &foo2); err != nil {
fmt.Println("json unmarshal err:", err)
return
}
fmt.Printf("foo2: %+v\n", foo2)
// json.Number -> int64
intValue, err := foo.Value.Int64()
if err != nil {
fmt.Println("value.Int64() err:", err)
return
}
fmt.Println("intValue:", intValue)
}
output:
foo: {Value:123}
foo2: {Value:123}
intValue: 123
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With