如何使用Golang检测JSON字符串中的重复属性?
检测JSON重复属性的Golang实现
在Golang里,标准的json.Unmarshal处理重复JSON键时会直接用后面的值覆盖前面的,所以如果想要检测重复属性,得手动基于json.Decoder做自定义解析才行。下面是具体的实现思路和代码:
核心思路
利用encoding/json包的Decoder逐个遍历JSON的Token,遇到对象的键时检查它是否已在当前对象层级中存在。因为JSON支持嵌套对象,所以需要用一个栈来跟踪不同层级的键集合,避免把不同对象里的同名键误判为重复。
具体实现步骤
- 初始化
json.Decoder,传入目标JSON字符串 - 用切片模拟栈,保存每个对象层级的已存在键集合(处理嵌套对象时入栈/出栈)
- 遍历每个Token,维护状态判断当前是否处于对象的键位置:
- 遇到
{时,向栈推入空map并标记期待键 - 遇到
}时,弹出栈顶map,根据栈是否为空更新期待键状态 - 遇到字符串且当前处于期待键状态时,检查栈顶map是否已有该键:存在则返回错误,不存在则存入map
- 处理其他类型Token时,根据当前是否在对象中更新期待键状态
- 遇到
完整代码示例
package main import ( "encoding/json" "errors" "fmt" "strings" ) func detectDuplicateKeys(jsonStr string) error { decoder := json.NewDecoder(strings.NewReader(jsonStr)) keyStack := []map[string]bool{} expectingKey := false for { token, err := decoder.Token() if err != nil { if errors.Is(err, json.ErrEOF) { return nil } return err } switch t := token.(type) { case json.Delim: switch t { case '{': keyStack = append(keyStack, make(map[string]bool)) expectingKey = true case '}': keyStack = keyStack[:len(keyStack)-1] expectingKey = len(keyStack) > 0 case '[': expectingKey = false case ']': expectingKey = len(keyStack) > 0 } case string: if expectingKey && len(keyStack) > 0 { currentKeys := keyStack[len(keyStack)-1] if currentKeys[t] { return fmt.Errorf("发现重复键: %q", t) } currentKeys[t] = true expectingKey = false } else { expectingKey = len(keyStack) > 0 } default: expectingKey = len(keyStack) > 0 } } } func main() { jsonStr := `{"a": "b", "a":true,"c":["field_3 string 1","field3 string2"]}` err := detectDuplicateKeys(jsonStr) if err != nil { fmt.Println("错误:", err) } else { fmt.Println("没有重复键") } }
代码说明
- 这个函数会遍历JSON的每个Token,跟踪每个对象层级的键,一旦发现同一对象内有重复键就立即返回错误
- 支持嵌套对象场景,比如
{"a": {"b":1, "b":2}}也能检测到重复的b键 - 数组内的对象也能正确处理,不会把不同对象的同名键误判为重复
运行上述代码后,会输出:错误: 发现重复键: "a",正好对应你给出的JSON字符串中的重复a键。
内容的提问来源于stack exchange,提问作者icelemon
相关产品推荐
相关产品推荐

