小编典典

检查字符串是否为JSON格式

go

如何检查给定的字符串是否采用以空格/换行符分隔的多个json字符串形式?

例如,
给定的:("test" 123 {"Name": "mike"}3个json与空格连接)
return :,true因为item("test" 123{"Name": "mike"})中的每个都是有效的json。

在Go中,我可以编写一个O(N ^ 2)函数,例如:

// check given string is json or multiple json concatenated with space/newline
func validateJSON(str string) error {
    // only one json string
    if isJSON(str) {
        return nil
    }
    // multiple json string concatenate with spaces
    str = strings.TrimSpace(str)
    arr := []rune(str)
    start := 0
    end := 0
    for start < len(str) {
        for end < len(str) && !unicode.IsSpace(arr[end]) {
            end++
        }
        substr := str[start:end]
        if isJSON(substr) {
            for end < len(str) && unicode.IsSpace(arr[end]) {
                end++
            }
            start = end
        } else {
            if end == len(str) {
                return errors.New("error when parsing input: " + substr)
            }
            for end < len(str) && unicode.IsSpace(arr[end]) {
                end++
            }
        }
    }
    return nil
}

func isJSON(str string) bool {
    var js json.RawMessage
    return json.Unmarshal([]byte(str), &js) == nil
}

但这不适用于大量输入。


阅读 251

收藏
2020-07-02

共1个答案

小编典典

有两种选择。从编码的角度来看,最简单的方法就是正常解码JSON字符串。您可以通过解码为空结构来提高效率:

package main

import "encoding/json"

func main() {
    input := []byte(`{"a":"b", "c": 123}`)
    var x struct{}
    if err := json.Unmarshal(input, &x); err != nil {
        panic(err)
    }

    input = []byte(`{"a":"b", "c": 123}xxx`) // This one fails
    if err := json.Unmarshal(input, &x); err != nil {
        panic(err)
    }
}

游乐场链接

此方法有一些潜在的缺点:

  • 它仅适用于单个JSON对象。也就是说,没有附加逻辑的情况下,对象列表(按问题的要求)将失败。
  • 正如@icza在评论中指出的那样,它仅适用于JSON对象,因此裸露的数组,数字或字符串将失败。为了适应这些类型,interface{}必须使用它,这可能会导致严重的性能损失。
  • 该扔掉的x值仍必须进行分配,以及至少一个反射调用是有可能的纸张,其可能引入显着的性能损失一些工作负载下。

鉴于这些限制,我的建议是使用第二个选项:遍历整个JSON输入,而忽略实际内容。使用标准库json.Decoder可简化此操作

package main

import (
    "bytes"
    "encoding/json"
    "io"
)

func main() {
        input := []byte(`{"a":"b", "c": 123}`)
        dec := json.NewDecoder(bytes.NewReader(input))
        for {
            _, err := dec.Token()
            if err == io.EOF {
                break // End of input, valid JSON
            }
            if err != nil {
                panic(err) // Invalid input
            }
        }

        input = []byte(`{"a":"b", "c": 123}xxx`) // This input fails
        dec = json.NewDecoder(bytes.NewReader(input))
        for {
            _, err := dec.Token()
            if err == io.EOF {
                break // End of input, valid JSON
            }
            if err != nil {
                panic(err) // Invalid input
            }
        }
}

游乐场链接

2020-07-02