2016-07-28 48 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

相关问题