Python Golang-检测JSON输入中的重复键
我最近完成了一个项目,在该项目中,我使用Python中的“对象挂钩”来检测JSON键是否是另一个键的副本。普通的JSON解码器似乎只给出遇到的最后一个值,但我希望能够检测并返回一个错误。我的新项目(在新公司)是用golang编写的,所以我想知道是否有类似于Python的对象钩子的方法。我还使用了另一个对象钩子来获得Python中的“有序dict”;本质上是JSON输入的列表形式,保留了原始JSON的顺序。在golang还没有被派去做这件事,但我打赌它会来的。。。。无论如何,对于与golang相关的这些JSON功能的输入,我们表示赞赏 您需要的是一个json库,它的工作原理类似于Python Golang-检测JSON输入中的重复键,python,json,go,Python,Json,Go,我最近完成了一个项目,在该项目中,我使用Python中的“对象挂钩”来检测JSON键是否是另一个键的副本。普通的JSON解码器似乎只给出遇到的最后一个值,但我希望能够检测并返回一个错误。我的新项目(在新公司)是用golang编写的,所以我想知道是否有类似于Python的对象钩子的方法。我还使用了另一个对象钩子来获得Python中的“有序dict”;本质上是JSON输入的列表形式,保留了原始JSON的顺序。在golang还没有被派去做这件事,但我打赌它会来的。。。。无论如何,对于与golang相关
bufio.Scanner
或SAX。一个是在这里实现的:。它将在扫描时生成事件,您可以使用这些事件来发现重复的密钥
下面是一个如何使用它的示例:
package main
import (
"fmt"
"github.com/garyburd/json"
"io"
"strings"
)
type Nothing struct{}
type Context struct {
Kind json.Kind
Keys map[string]Nothing
}
func Validate(rdr io.Reader) error {
scanner := json.NewScanner(rdr)
stack := []Context{}
for scanner.Scan() {
if scanner.Kind() == json.Object || scanner.Kind() == json.Array {
stack = append(stack, Context{
Kind: scanner.Kind(),
Keys: map[string]Nothing{},
})
} else if scanner.Kind() == json.End {
if len(stack) == 0 {
return fmt.Errorf("expected start object or array")
}
stack = stack[:len(stack)-1]
} else if len(stack) > 0 {
current := stack[len(stack)-1]
if current.Kind == json.Object {
key := string(scanner.Name())
_, exists := current.Keys[key]
if exists {
return fmt.Errorf("found duplicate key: %v", key)
}
current.Keys[key] = Nothing{}
}
}
}
return nil
}
func main() {
rdr := strings.NewReader(`
{
"x": 10,
"y": {
"z": 1,
"z": 2
},
"z": [1,2,3,4,5]
}
`)
err := Validate(rdr)
if err == nil {
fmt.Println("valid json!")
} else {
fmt.Println("invalid json:", err)
}
}
当它遍历JSON对象时,它会构建一个哈希表堆栈。(对于嵌套对象/数组)其中一个哈希表中的任何重复键都会导致错误。如果需要更多详细信息,可以轻松地将
名称
属性添加到上下文
中,并向后遍历堆栈以生成json路径。(如a.b.c.d是一个重复的键
)json中的重复键不是有效的json。是吗?Go中的JSON解码器允许通过解组器接口进行自定义反序列化。您可以使用这个接口来支持Python的json
库中的对象钩子机制@fabrizioM是正确的,但由于手动生成或手动编辑,有时会显示无效的JSON。我使用的Python JSON包默默地忽略了重复的键;如果您解码这个伪json:a:1、b:2、a:3,它将为您提供b:2、a:3作为输出-最后一个键值胜过先前的值。我更希望它在这个问题上出错,而不是默默地失败。看起来JSON扫描程序的github repo已经不存在了。