Reputation: 356
I have a coords coming back in JSON
Whilst the API should always return them correct as an array of size 2, how can we enforce the structure is correct and raise an error when unmarshaling (apart from a very manual process). See example case if json is invalid.
package main
import (
"fmt"
"encoding/json"
)
// ResultType
type Location struct {
Coordinates [2]int `json:"coords,array[20]"`
}
func main() {
fmt.Println("Hello, playground")
result := Location{}
jsonBodyTooManyCoords := `{"coords": [1, 2, 3]}`
json.Unmarshal([]byte(jsonBodyTooManyCoords), &result)
fmt.Println(result) // Prints {1, 2}
result = Location{}
jsonBodyTooManyCoords = `{"coords": [1]}`
json.Unmarshal([]byte(jsonBodyTooManyCoords), &result)
fmt.Println(result) // Prints {1, 0}
}
Upvotes: 0
Views: 699
Reputation: 79526
This sort of enforcement requires a custom type and custom unmarshaler. You could do something like this:
type coord [2]int
func (c *coord) UnmarshalJSON(data []byte) error {
var x []int
if err := json.Unmarshal(data, &x); err != nil {
return err
}
if len(x) > 2 {
return errors.New("Too many values")
}
if len(x) < 2 {
return errors.New("Too few values")
}
copy((*c)[:], x)
return nil
}
Then use your custom type:
// ResultType
type Location struct {
Coordinates coord `json:"coords,array[20]"`
}
Upvotes: 0
Reputation: 42433
[H]ow can we enforce the structure is correct and raise an error when unmarshaling [...]?
You cannot.
Excess elements are silently discarded and missing values are returned as a zero value (both facts are documented in the documentation of encoding/json).
Also note that there is no array modifier, so your struct tags json:"cords,array[20]"
seem strange.
If you want/need to handle malformed JSON array: Unmarshal into a slice and check its length.
Upvotes: 1