【问题标题】:Check if JSON is Object or Array检查 JSON 是对象还是数组
【发布时间】:2019-03-06 01:09:53
【问题描述】:

Go 中是否有一种简单的方法来检查给定的 JSON 是 Object {} 还是数组 []

首先想到的就是将json.Unmarshal()变成一个界面,然后看看是变成了地图,还是地图的切片。但这似乎效率很低。

我可以检查第一个字节是{ 还是[?或者有没有更好的方法已经存在。

【问题讨论】:

    标签: json go unmarshalling


    【解决方案1】:

    使用以下内容来检测 []bytedata 中的 JSON 文本是否为数组或对象:

     // Get slice of data with optional leading whitespace removed.
     // See RFC 7159, Section 2 for the definition of JSON whitespace.
     x := bytes.TrimLeft(data, " \t\r\n")
    
     isArray := len(x) > 0 && x[0] == '['
     isObject := len(x) > 0 && x[0] == '{'
    

    这段代码的 sn-p 处理可选的前导空格,并且比解组整个值更有效。

    因为 JSON 中的顶级值也可以是数字、字符串、布尔值或 nil,所以 isArrayisObject 可能都评估为 false。当 JSON 无效时,值 isArrayisObject 也可以评估为 false。

    【讨论】:

    • 正是我想要的,谢谢。我不必担心顶级值是我用例中的其他任何东西,因为无论如何它们都是无效的。
    【解决方案2】:

    使用类型开关来确定类型。这类似于 Xay 的答案,但更简单:

    var v interface{}
    if err := json.Unmarshal(data, &v); err != nil {
        // handle error
    }
    switch v := v.(type) {
    case []interface{}:
        // it's an array
    case map[string]interface{}:
        // it's an object
    default:
        // it's something else
    }
    

    【讨论】:

    • 我觉得这是最好的答案,因为 json 已经过验证,而且简单明了。
    • 这个效率很低。
    • 这是我首先想到的,但它的效率肯定较低,尤其是考虑到在 Unmarshal 内部使用反射。
    • @robbieperry22 效率低,但是Unmarshal在unmarhsalling到interface{}时不使用反射。
    【解决方案3】:

    使用json.Decoder 逐步解析您的 JSON。与其他答案相比,这具有以下优势:

    1. 比解码整个值更高效
    2. 使用官方 JSON 解析规则,如果输入无效,则会生成标准错误。

    请注意,此代码未经测试,但应该足以让您了解。如果需要,它还可以轻松扩展以检查数字、布尔值或字符串。

    func jsonType(in io.Reader) (string, error) {
        dec := json.NewDecoder(in)
        // Get just the first valid JSON token from input
        t, err := dec.Token()
        if err != nil {
            return "", err
        }
        if d, ok := t.(json.Delim); ok {
            // The first token is a delimiter, so this is an array or an object
            switch (d) {
            case "[":
                return "array", nil
            case "{":
                return "object", nil
            default: // ] or }
                return nil, errors.New("Unexpected delimiter")
            }
        }
        return nil, errors.New("Input does not represent a JSON object or array")
    }
    

    注意,这消耗了in 的前几个字节。如有必要,读者可以进行复制。如果您尝试从字节切片 ([]byte) 中读取,请先将其转换为阅读器:

    t, err := jsonType(bytes.NewReader(myValue))
    

    【讨论】:

      猜你喜欢
      • 2012-04-06
      • 1970-01-01
      • 2020-05-29
      • 2015-01-24
      • 1970-01-01
      • 2017-06-18
      • 2021-02-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多