2016-07-28 85 views
4

我想看看是否以.json文件具有相同的鍵解編時,檢查JSON對象具有相同的密鑰

"gauge1":{ 
    "name":"someName", 
    "name":"someName1" 
} 

多的倍數是有沒有去的方式來檢查,如果json中的密鑰'name'被多次使用? 在去,如果你解組具有相同名稱的多個按鍵的JSON文件,這將改寫先前寫入密鑰和gauge1.name將成爲someName1

任何幫助將不勝感激,謝謝!

回答

1

按說你應該使用encoding/json包—的低級別的解碼設備,即它的Decoder類型,其方法Token()遍歷輸入JSON流中的所有令牌。

結合狀態機和地圖(或地圖層次結構)來保留解析出來的值,這種方法將允許您檢查是否在正在解析的JSON對象中看到同名的兄弟字段。

3

您可以創建一個json.Unmarshaler字符串類型,如果它在解組時被分配了多次,則會返回一個錯誤。

type singleAssignString string 

func (s *singleAssignString) UnmarshalJSON(b []byte) error { 
    if s != nil && *s != "" { 
     return fmt.Errorf("multiple string assignment") 
    } 

    *s = singleAssignString(string(b)) 
    return nil 
} 

https://play.golang.org/p/v4L1EjTESX

json.Decoder處理這可能是唯一的正確獲取所有字段,並返回一個良好的錯誤信息的方式。您可以使用外部類型的UnmarshalJSON方法中的嵌入式解碼器執行此操作。一個粗略的例子可能是這樣的:

type Data struct { 
    Name string 
} 

func (d *Data) UnmarshalJSON(b []byte) error { 
    dec := json.NewDecoder(bytes.NewReader(b)) 

    key := "" 
    value := "" 

    for dec.More() { 
     tok, err := dec.Token() 
     if err != nil { 
      return err 
     } 

     s, ok := tok.(string) 
     if !ok { 
      continue 
     } 

     switch { 
     case key == "": 
      key = s 
      continue 
     case value == "": 
      value = s 
     } 

     if key == "Name" { 
      if d.Name != "" { 
       return fmt.Errorf("multiple assignment to Name") 
      } 
      d.Name = s 
     } 

     key = "" 

    } 
    return nil 
} 
+0

與第一種方法的一個嚴重問題是,unmarshaler沒有它檢測到您出爐字段的名稱到錯誤信息錯誤的情況下的想法,但你應該需要。檢查對象的所有字段,這將是不切實際的(缺少爲每個字段的值定義自定義類型)。所以我會爲第二個投票:雖然肯定更復雜,但當檢測到錯誤時,它會在違規密鑰中檢測到,而不是其值。 – kostix

+0

@kostix:我同意。您可以通過使外部結構體結構實現自己的'UnmarshlJSON'來解決這個問題,在那裏解組並返回一個'UnmarshalFieldError'或另一個更多的信息性消息。但是,是的,我認爲唯一的「正確」方法是單獨處理每個令牌的解碼。 – JimB

相關問題