[英]How to list unknown fields after json parsing
Imagine we have following Go structs: 假设我们有以下Go结构:
type Config struct {
Name string `json:"name,omitempty"`
Params []Param `json:"params,omitempty"`
}
type Param struct {
Name string `json:"name,omitempty"`
Value string `json:"value,omitempty"`
}
and following json: 并跟随json:
{
"name": "parabolic",
"subdir": "pb",
"params": [{
"name": "input",
"value": "in.csv"
}, {
"name": "output",
"value": "out.csv",
"tune": "fine"
}]
}
and we do unmarshalling: 我们会进行编组:
cfg := Config{}
if err := json.Unmarshal([]byte(cfgString), &cfg); err != nil {
log.Fatalf("Error unmarshalling json: %v", err)
}
fmt.Println(cfg)
https://play.golang.org/p/HZgo0jxbQrp https://play.golang.org/p/HZgo0jxbQrp
Output would be {parabolic [{input in.csv} {output out.csv}]}
which makes sense - unknown fields were ignored. 输出将是
{parabolic [{input in.csv} {output out.csv}]}
,这很有意义-未知字段将被忽略。
Question: how to find out which fields were ignored? 问题:如何找出哪些字段被忽略?
Ie getIgnoredFields(cfg, cfgString)
would return ["subdir", "params[1].tune"]
即
getIgnoredFields(cfg, cfgString)
将返回["subdir", "params[1].tune"]
(There is a DisallowUnknownFields
option but it's different: this option would result Unmarshal
in error while question is how to still parse json without errors and find out which fields were ignored) (有一个
DisallowUnknownFields
选项,但有所不同:此选项将导致Unmarshal
错误,而问题是如何仍然解析JSON而不会出现错误,并找出哪些字段被忽略了)
Not sure if that is the best way but what I did is: 不知道这是否是最好的方法,但是我所做的是:
If current-level type is map: 如果当前级别类型是map:
If current level type is array: 如果当前级别类型为数组:
Code: 码:
// ValidateUnknownFields checks that provided json
// matches provided struct. If that is not the case
// list of unknown fields is returned.
func ValidateUnknownFields(jsn []byte, strct interface{}) ([]string, error) {
var obj interface{}
err := json.Unmarshal(jsn, &obj)
if err != nil {
return nil, fmt.Errorf("error while unmarshaling json: %v", err)
}
return checkUnknownFields("", obj, reflect.ValueOf(strct)), nil
}
func checkUnknownFields(keyPref string, jsn interface{}, strct reflect.Value) []string {
var uf []string
switch concreteVal := jsn.(type) {
case map[string]interface{}:
// Iterate over map and check every value
for field, val := range concreteVal {
fullKey := fmt.Sprintf("%s.%s", keyPref, field)
subStrct := getSubStruct(field, strct)
if !subStrct.IsValid() {
uf = append(uf, fullKey[1:])
} else {
subUf := checkUnknownFields(fullKey, val, subStrct)
uf = append(uf, subUf...)
}
}
case []interface{}:
for i, val := range concreteVal {
fullKey := fmt.Sprintf("%s[%v]", keyPref, i)
subStrct := strct.Index(i)
uf = append(uf, checkUnknownFields(fullKey, val, subStrct)...)
}
}
return uf
}
Full version: https://github.com/yb172/json-unknown/blob/master/validator.go 完整版本: https : //github.com/yb172/json-unknown/blob/master/validator.go
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.