Veaxen
Veaxen

Reputation: 51

Go : How to ignore type mismatch error when json.Unmarshal to struct?

Assume I have a struct like

type A struct {
    Val1 int `json:"val1"`
    Val2 int `json:"val2"`
}

then:

str := `{"val1": "abc", "val2": 2}`
var a A
error := json.Unmarshal([]byte(jsonString),&a)

How can I ingore val1 type mismatch error? I just want to ignore errors when the types don’t match, and parse normally if they match.

Upvotes: 1

Views: 2929

Answers (2)

AndresVia
AndresVia

Reputation: 171

Don't try to decode it into a struct{} instead decode into a map[string]any then type assert the JSON fields you are interested in. The library mapstructure (from hashicorp) may be useful to convert back-and-forth between map[string]any and struct{}

You have to consider that according to JSON all numbers are float64 and that not all float64 can fit in a int64 or int

func asInt(val any) (i *int, err error) {
    jsonNumeric, ok := val.(float64)
    if !ok {
        err = errors.New("value is not a number")
        return
    }
    if jsonNumeric < float64(math.MinInt64) || jsonNumeric > float64(math.MaxInt64) {
        err = errors.New("value is too big to be an int64")
        return
    }
    bigInt := int64(jsonNumeric)
    if bigInt < math.MinInt || bigInt > math.MaxInt {
        err = errors.New("value is too big to be an int")
        return
    }
    regInt := int(bigInt)
    i = &regInt
    return
}

func main() {
    jsonString := `{"val1": "abc", "val2": 2}`
    var m map[string]any
    if err := json.Unmarshal([]byte(jsonString), &m); err != nil {
        panic(err)
    }
    val1, err := asInt(m["val1"])
    if err != nil {
        log.Print(err)
    }
    val2, err := asInt(m["val2"])
    if err != nil {
        log.Print(err)
    }
    fmt.Printf("%t %t\n", val1 != nil, val2 != nil) // prints "false true"
}

Upvotes: 1

Volker
Volker

Reputation: 42433

How can I ingore val1 type mismatch error? I just want to ignore errors when the types don’t match, and parse normally if they match.

You cannot do that.

The best thing you can do is have the type e.g. interface{} or json.Number and decide later.

Upvotes: 1

Related Questions