问题
My struct:
type User struct {
FirstName string `json:"firstname, omitempty" validate:"required"`
LastName string `json:"lastname, omitempty" validate:"required"`
NumberofDays int `json:"numberofdays, string" validate:"min=0,max=100"`
}
Value for NumberofDays is passed as string from the server but I want to check if it is within range and store as int.
Ex: user := &User{"Michael","Msk","3"}
I'm getting 'cannot unmarshal string into Go value of type int'.
I'm not sure how to typecast to int and do the validation
回答1:
Remove the space after the comma in the struct tags, e.g. json:"numberofdays, string"
should be json:"numberofdays,string"
. With the space, the json
package ignores the string
part, hence the error message you're getting. Without the space, the error goes away and behavior is as expected.
Demo comparing the two here: https://play.golang.org/p/AUImnw_PIS
Documentation of json
package struct tags: https://golang.org/pkg/encoding/json/#Marshal
回答2:
You can use a custom type to unmarshal a string to an integer value using whatever set of parsing rules you want this mapping to use:
package main
import (
"encoding/json"
"fmt"
"strconv"
)
type User struct {
FirstName string `json:"firstname,omitempty" validate:"required"`
LastName string `json:"lastname,omitempty" validate:"required"`
NumberofDays StrInt `json:"numberofdays" validate:"min=0,max=100"`
}
type StrInt int
func (si *StrInt) UnmarshalJSON(b []byte) error {
var s string
err := json.Unmarshal(b, &s)
if err != nil {
return err
}
n, err := strconv.ParseInt(s, 10, 0)
if err != nil {
return err
}
*si = StrInt(n)
return nil
}
const data = `{
"FirstName": "John",
"LastName": "Doe",
"NumberOfDays": "42"
}`
func main() {
var u User
err := json.Unmarshal([]byte(data), &u)
if err != nil {
panic(err)
}
fmt.Println(u)
}
Playground.
The idea is as follows:
- Have a custom type which is mostly
int
but allows defining custom methods on it. - Have that type satisfy the
encoding/json.Unmarshaler
interface by implementing theUnmarshalJSON()
method on a pointer to that type. - In the method, first unmarshal the value as its native type—
string
—and then parse it as an integer.
This approach might appear to be weird, but if you'll think of it a bit more, there's no single "true" string representation of an integer: there are different bases and different conventions at representing integers even in a particular base.
In your unmarshaling method you implement the policy of the text representation of your integers.
回答3:
The json package defines a custom type json.Number
for these cases.
来源:https://stackoverflow.com/questions/47206552/how-do-i-unmarshal-a-string-value-from-a-json-document-into-a-variable-of-type-i