检查JSON是对象还是数组

时间:2019-03-06 01:09:53

标签: json go unmarshalling

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

首先想到的是将json.Unmarshal()插入接口,然后查看它是否成为地图或地图切片。但这似乎效率很低。

我可以只检查第一个字节是{还是[吗?还是有一种更好的方法可以做到这一点?

3 个答案:

答案 0 :(得分:7)

使用以下内容来检测[]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] == '{'

此代码段处理可选的前导空白,并且比解组整个值更有效。

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

答案 1 :(得分: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
}

答案 2 :(得分:2)

使用json.Decoder对JSON进行逐步解析。与其他答案相比,它具有以下优势:

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

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

type 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")
}

请注意,此{em>已消耗 in的前几个字节。如有必要,这是读者的一项练习。如果您要尝试读取字节片([]byte),请先将其转换为读取器:

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