简体   繁体   中英

How to detect if received JSON has unknown fields

I'm trying to find some way to prohibit arbitrary JSON keys and fields in Go. For now, if I send payload with undeclared fields in struct, the service will work normally and will map the entity described fields (like json:"id,omitempty" ). For example:

type Foo struct {
    Bar         int        `json:"id,omitempty"`
}

Received JSON:

{
  "id": 12,
  "hey": "hey"
}

Can anybody help me to find the way of tracking unknown field in payload? I need to return an error in that case.

Update:

you might want to use DisallowUnknownFields() read for more info


old answer:

There is a proposal for golang 1.9 on this: proposal: some way to reject unknown fields in encoding/json.Decoder

Till then you could try something like this playground (code also below). The key idea is to parse the json into a map[string]interface{} and then work with the keys. This will of course get much more complicated if you have nested structs.

package main

import (
    "encoding/json"
    "fmt"
)

type Foo struct {
    Bar int `json:"id,omitempty"`
}
var allowedFooKeys = []string{"id"}

func main() {
    b := []byte(`{
      "id": 12,
      "hey": "hey"
    }`)
    m := map[string]interface{}{}

    if err := json.Unmarshal(b, &m); err != nil {
        panic(err)
    }

    for k, _ := range m {
        if !keyExists(k, allowedFooKeys) {
            fmt.Println("Disallowed key in JSON:", k)
        }
    }
}

func keyExists(key string, keys []string) bool {
    for _, k := range keys {
        if k == key {
            return true
        }
    }
    return false
}

You can even get rid of the variable allowedFooKeys by getting the allowed keys directly from the Foo struct using reflect. For more info on that see here: How to read struct field ` ` decorators?

Since Go 1.10, the JSON decoder provides the DisallowUnknownFields() option for this use case.

func StrictUnmarshal(data []byte, v interface{}) error {
    dec := json.NewDecoder(bytes.NewReader(data))
    dec.DisallowUnknownFields()
    return dec.Decode(v)
}

You can find a full working example here:

https://go.dev/play/p/HoGDIt8nJB7

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