简体   繁体   中英

How to strictly unmarshall a go fixed length array?

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}
}

[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.

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]"`
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM