如何检查给定的字符串是否采用以空格/换行符分隔的多个json字符串形式?
例如, 给定的:("test" 123 {"Name": "mike"}3个json与空格连接) return :,true因为item("test" 123和{"Name": "mike"})中的每个都是有效的json。
"test" 123 {"Name": "mike"}
true
"test"
123
{"Name": "mike"}
在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 }
但这不适用于大量输入。
有两种选择。从编码的角度来看,最简单的方法就是正常解码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) } }
(游乐场链接)
此方法有一些潜在的缺点:
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 } } }