簡體   English   中英

json解析后如何列出未知字段

[英]How to list unknown fields after json parsing

假設我們有以下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"`
}

並跟隨json:

{
    "name": "parabolic",
    "subdir": "pb",
    "params": [{
        "name": "input",
        "value": "in.csv"
    }, {
        "name": "output",
        "value": "out.csv",
        "tune": "fine"
    }]
}

我們會進行編組:

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

輸出將是{parabolic [{input in.csv} {output out.csv}]} ,這很有意義-未知字段將被忽略。

問題:如何找出哪些字段被忽略?

getIgnoredFields(cfg, cfgString)將返回["subdir", "params[1].tune"]

(有一個DisallowUnknownFields選項,但有所不同:此選項將導致Unmarshal錯誤,而問題是如何仍然解析JSON而不會出現錯誤,並找出哪些字段被忽略了)

不知道這是否是最好的方法,但是我所做的是:

  1. 如果當前級別類型是map:

    1. 檢查所有映射鍵是否已知。
      • 鍵可以是結構字段名稱,也可以是映射鍵。
      • 如果未知-添加到未知字段列表
    2. 遞歸重復與每個鍵對應的值
  2. 如果當前級別類型為數組:

    1. 為每個元素遞歸運行

碼:

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

完整版本: https : //github.com/yb172/json-unknown/blob/master/validator.go

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM