检查字符串是否为 JSON 格式

2024-03-14

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

例如,
given: "test" 123 {"Name": "mike"}(3个json用空格连接)
返回:true,因为每个项目 ("test" 123 and {"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
}

但这对于大输入不起作用。


有两种选择。从编码的角度来看,最简单的方法就是正常解码 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)
    }
}

(游乐场链接 https://play.golang.org/p/VheJf-cd-yD)

这种方法有一些潜在的缺点:

  • 它仅适用于单个 JSON 对象。也就是说,如果没有额外的逻辑,对象列表(如问题中所要求的)将失败。
  • 正如 @icza 在评论中指出的,它仅适用于 JSON 对象,因此裸数组、数字或字符串将失败。为了适应这些类型,interface{}必须使用,这可能会导致一些严重的性能损失。
  • 扔掉的x仍然必须分配值,并且表下可能至少有一个反射调用,这可能会给某些工作负载带来明显的性能损失。

鉴于这些限制,我的建议是使用第二个选项:循环遍历整个 JSON 输入,忽略实际内容。使用标准库使这变得简单json.解码器 https://golang.org/pkg/encoding/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
            }
        }
}

(游乐场链接 https://play.golang.org/p/QHYK3aCEImk)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

检查字符串是否为 JSON 格式 的相关文章

随机推荐

  • 使用 C++11,我还需要用于 Unicode 文本的非标准字符串操作库吗?

    我注意到 std string 的 length 方法返回以字节为单位的长度 而 std u16string 中的相同方法返回 2 字节序列的数量 我还注意到 当字符或代码点位于 BMP 之外时 长度返回 4 而不是 2 此外 Unicod
  • Angular 2:模板上未定义 OnInit 期间设置的属性

    我有这个组件 export class CategoryDetailComponent implements OnInit category Category categoryProducts Product errorMessage st
  • 在现有表 Oracle 上创建索引

    在oracle中的现有表上创建索引安全吗 像这样 CREATE INDEX table sample ix03 ON table sample col4 col22 TABLESPACE data STORAGE INITIAL 10M N
  • DecisionTreeRegressor 的 Predict_proba 的等效项

    scikit learn 的DecisionTreeClassifier支持通过以下方式预测每个类别的概率predict proba 功能 这不存在于DecisionTreeRegressor AttributeError Decision
  • CSS“反向边框半径”在元素的边界框之外创建手机凹口设计[重复]

    这个问题在这里已经有答案了 我正在尝试使用 HTML 和 CSS 创建看起来像手机的东西 并且我希望相机具有类似 倒置边框半径 的东西 可以将其与框架顺利连接 我不能只是将其放大并使用具有白色背景的伪元素掩盖不需要的区域 因为屏幕内容可能并
  • 如何生成 n 个相关项的二项式向量?

    我想根据多个相关项生成一个二项式向量 每个相关项都有一个定义的概率 当我使用 e G rbinom 1e3 size 4 prob c p x1 p x2 p x3 p x4 我得到类似的东西3 3 0 0 2 4 1 0 4 4 0 1
  • nginx 不提供更新的静态文件

    从apache切换到nginx 遇到了一些奇怪的事情 1 假设我网站的文档根目录中有一个 to txt 文件 其中包含 foo curl http localhost yo txt gt foo 2 然后我更改文件以包含 bar curl
  • 您使用什么来部署 Web 应用程序? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Visual Studio 2017加载崩溃解决方案

    我的 VS 2017 不断崩溃 并在 EventViewer 中出现以下错误 知道为什么会崩溃吗 Exception Info System InvalidOperationException at System Linq Enumerab
  • Test Flight Beta 测试:Xcode 6.3 Beta 4 未显示崩溃

    我正在关注新的试飞程序 我开发了一个应用程序 我通过 Xcode 提交到 iTunes Connect 门户 如果UIButton被点击 由于该应用程序可用于内部测试人员的 Beta 测试 因此我希望在新版本中看到崩溃日志CrashesXc
  • 如何将两个值合并/组合成同一数组中的单个键

    我不确定我的标题使用什么合适的术语 但只是想知道下面的解决方案需要将两个值合并 组合成一个关联数组中的一个 例如我有这个数组 Array 1 gt Array agent name 1 gt Agent 1 agent phone 1 gt
  • 使用 Xamarin 在可移植类库中安全地绑定 WCF

    我有一个 WCF 服务WSHttpBinding 不幸的是 在我的 PCL 中 由于某种原因我无法使用WSHttpBinding 我只能用BasicHttpBinding 有没有一种方法可以在可移植类库中使用安全绑定 我正在使用 Xamar
  • 如何从 Google 登录中检索年龄和性别

    我已将 Google 登录集成到我的 iOS 应用程序中 我想访问用户的性别和年龄 该文档不够清楚 无法了解如何执行此操作 我发现我应该请求正确的范围 我没有在文档中找到正式的范围列表 并且我不知道应该使用哪个范围 我也不知道当我得到数据时
  • 用于编辑 PROJECT-Info.plist 文件的 CFBundleVersion 字段的 Bash 脚本

    为了建立持续集成系统 Hudson 我编写了一个 bash 脚本来自动构建 Xcode 项目 此外 在调试配置中 要求我将项目的 svn 修订号插入 PROJECT Info plist 文件的 CFBundleRevision 字段中 作
  • 在 Linq-to-SQL 中模拟多表继承

    到目前为止 每个人都知道 Linq to SQL 本身并不支持多表继承 也称为每个子类型一个表 如果您想要本机支持 您可以使用其他 ORM 框架 例如 Entity Framework NHibernate 等 支持多表继承 参考SO问题
  • 有没有办法提高大文件解析日期的速度? [复制]

    这个问题在这里已经有答案了 我正在读取一个大约有 1B 行的大 csv 文件 我在解析日期时遇到了问题 Python 的处理速度很慢 文件中的一行如下所示 20170427 20 52 01 510 ABC USD MXN 1 OFFER
  • 更改不同屏幕上的列顺序

    基本上我想使用 bootstrap 实现的目标是这样的 https ibb co mBB9P6P https ibb co mBB9P6P 当它调整到较小的屏幕时 它应该喜欢 https ibb co 0XnDy2S https ibb c
  • SQL 中的 GROUP BY 和 HAVING

    如果我写 SELECT continent FROM world GROUP BY continent HAVING sum population gt 100000000 它将返回总金额超过 1 亿的所有大陆 但如果我像这样省略 GROU
  • DSN 无连接(MS Access to SQL 2016)

    当我想将链接表转换为 DSNLess 连接时 我有一个有效的解决方案 http www accessmvp com DJSteele DSNLessLinks html http www accessmvp com DJSteele DSN
  • 检查字符串是否为 JSON 格式

    如何检查给定的字符串是否是由空格 换行符分隔的多个 json 字符串的形式 例如 given test 123 Name mike 3个json用空格连接 返回 true 因为每个项目 test 123 and Name mike 是一个有