This is my opinion. In case you need to deal with a few additional cases. Add more as needed.
// so you know what needed. import ( "encoding/json" "strconv" "strings" ) // NumBool provides a container and unmarshalling for fields that may be // boolean or numbrs in the WebUI API. type NumBool struct { Val bool Num float64 } // UnmarshalJSON parses fields that may be numbers or booleans. func (f *NumBool) UnmarshalJSON(b []byte) (err error) { switch str := strings.ToLower(strings.Trim(string(b), '"')); str { case "true": f.Val = true case "false": f.Val = false default: f.Num, err = strconv.ParseFloat(str, 64) if f.Num > 0 { f.Val = true } } return err }
I see it on the playground .
I was also known for something like this:
// FlexBool provides a container and unmarshalling for fields that may be // boolean or strings in the Unifi API. type FlexBool struct { Val bool Txt string } // UnmarshalJSON method converts armed/disarmed, yes/no, active/inactive or 0/1 to true/false. // Really it converts ready, ok, up, t, armed, yes, active, enabled, 1, true to true. Anything else is false. func (f *FlexBool) UnmarshalJSON(b []byte) error { if f.Txt = strings.Trim(string(b), '"'); f.Txt == "" { f.Txt = "false" } f.Val = f.Txt == "1" || strings.EqualFold(f.Txt, "true") || strings.EqualFold(f.Txt, "yes") || strings.EqualFold(f.Txt, "t") || strings.EqualFold(f.Txt, "armed") || strings.EqualFold(f.Txt, "active") || strings.EqualFold(f.Txt, "enabled") || strings.EqualFold(f.Txt, "ready") || strings.EqualFold(f.Txt, "up") || strings.EqualFold(f.Txt, "ok") return nil }
And if you want to go very small:
// Bool allows 0/1 to also become boolean. type Bool bool func (bit *Bool) UnmarshalJSON(b []byte) error { txt := string(b) *bit = Bool(txt == "1" || txt == "true") return nil }
Watch it on the playground .