如何检查一个字符串是否为有效的JSON字符串?

810
isJsonString('{ "Id": 1, "Name": "Coke" }')
应该是true
isJsonString('foo')
isJsonString('<div>foo</div>')

应该是false

我正在寻找一种不使用try/catch的解决方案,因为我的调试器设置为"在所有错误上中断",这会导致它在无效的JSON字符串上中断。


5
对于那些好奇的人,这是V8引擎如何进行JSON解析的方式:http://v8.googlecode.com/svn/trunk/src/json-parser.h - A T
8
使用 try catch 仅需 2 行代码即可检查 JSON 字符串的有效性。代码如下: var isValidJSON = true; try { JSON.parse(jsonString) } catch { isValidJSON = false; } - efkan
24
虽然这种做法可行,但非常笨拙且不符合最佳实践。Try/catch 应该用于异常情况和错误处理,而不是一般的程序流程控制。 - Tasgall
35
通常情况下是这样的。但如果使用 try/catch 方法比任何基于验证器的方法更有效呢?难道因为另一种选择是“不好的做法”,就选择(有时明显)更慢的选项吗?使用 try/catch 方法没有功能上的问题,所以没有理由不使用它。重要的是让新程序员开发良好的编码标准,但同样重要的是不要强化对传统指南的盲目遵循,特别是在指南使事情变得比必要的更加困难的情况下。 - Abion47
这是最好的答案,但被压缩了:function isJsonString(json){try{var o=JSON.parse(json);if(o&&typeof o==="object"){return o}}catch(e){}return false}...,如果json无效,则返回解析后的对象,否则返回False - ashleedawg
显示剩余2条评论
28个回答

1346

使用类似于JSON.parse的 JSON 解析器:

function isJsonString(str) {
    try {
        JSON.parse(str);
    } catch (e) {
        return false;
    }
    return true;
}

12
谢谢你,但我刚与团队一起运行了这个程序,他们希望不使用try/catch。问题已经被编辑并更改了标题。对此我们表示歉意。 - Chi Chan
6
因为1不是一个字符串,所以它会这样做,尝试使用"1"。 - Purefan
18
这个答案存在问题,如果字符串验证无误并且您解析它,那么您将解析两次。您是否可以在无法解析时返回 false,而在解析成功时返回该对象,以避免这种情况? - Carcigenicate
18
你可以这样做。然而,JSON.parse("false") 的计算结果也是false - Gumbo
7
这是因为"12345678"是一个有效的JSON字符串。JSON文档只有一个根节点,可以是null、布尔值、数字、字符串、数组或对象。 - SwammiM
显示剩余12条评论

589

我知道我回答这个问题已经晚了3年,但我还是想发表一下意见。

虽然Gumbo的解决方案很好,但它无法处理一些情况,比如JSON.parse({something that isn't JSON})没有引发异常的情况。

我更喜欢同时返回解析后的JSON,这样调用代码就不必再调用JSON.parse(jsonString)一次。

这对我的需求似乎很有效:

/**
 * If you don't care about primitives and only objects then this function
 * is for you, otherwise look elsewhere.
 * This function will return `false` for any valid json primitive.
 * EG, 'true' -> false
 *     '123' -> false
 *     'null' -> false
 *     '"I'm a string"' -> false
 */
function tryParseJSONObject (jsonString){
    try {
        var o = JSON.parse(jsonString);

        // Handle non-exception-throwing cases:
        // Neither JSON.parse(false) or JSON.parse(1234) throw errors, hence the type-checking,
        // but... JSON.parse(null) returns null, and typeof null === "object", 
        // so we must check for that, too. Thankfully, null is falsey, so this suffices:
        if (o && typeof o === "object") {
            return o;
        }
    }
    catch (e) { }

    return false;
};

16
在这一页的回答中,这个是最强大和可靠的。 - Jonline
41
o && o !== null 是多余的。 - Aleksei Matiushkin
4
在使用typeof时,使用三个等号也是可以的,它总是返回一个字符串。 :) - Hein Haraldson Berg
7
虽然这是一篇旧帖子,但我认为值得展示一个fiddle来演示你@matth的答案。请注意,对象将无效,您必须传递JSON字符串。对于任何刚开始学习的人可能会有所帮助。 - stackunderflow
8
函数应该返回 undefined 而不是 false,因为 false 是一个有效的 JSON 字符串,并且无法区分 tryParseJSON("false")tryParseJSON("garbage") - sparebytes
显示剩余16条评论

206
首先是一条注释。问题是关于不使用 try/catch 的。
如果你可以使用它,请阅读下面的答案。 这里我们只是使用一个正则表达式来检查 JSON 字符串,它适用于大多数情况,但不是所有情况。

请查看位于https://github.com/douglascrockford/JSON-js/blob/master/json2.js第450行附近。

有一个正则表达式用于检查有效的 JSON,像这样:

if (/^[\],:{}\s]*$/.test(text.replace(/\\["\\\/bfnrtu]/g, '@').
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {

  //the json is ok

}else{

  //the json is not ok

}

编辑:json2.js的新版本进行了更高级的解析,但仍基于正则表达式替换(来自@Mrchief的评论)。


70
这仅检查代码是否适用于eval的使用。例如,以下字符串“2011-6-27”将通过该测试。 - SystemicPlural
4
@SystemicPlural,是的,但问题是关于不使用try/catch。 - Mic
15
在JavaScript中,你无法使用正则表达式来测试一个字符串是否是有效的JSON,因为JS的正则表达式不支持必要的扩展(递归正则表达式),这样做是行不通的。你上面的代码在遇到"{"时会失败。 - Venge
10
仅仅因为它对他有帮助,并不意味着它对我们这些多年后也有同样问题的人有帮助。 - McKay
3
JSON.parse 的速度更快,大约只需 0.2 毫秒就能完成任务,而这个 if 比较需要大约 0.9 毫秒。 - Machado
显示剩余12条评论

88
// vanillaJS
function isJSON(str) {
    try {
        return (JSON.parse(str) && !!str);
    } catch (e) {
        return false;
    }
}

用法: isJSON({})将返回falseisJSON('{}')将返回true

检查某个东西是否为ArrayObject(已解析的JSON):

// vanillaJS
function isAO(val) {
    return val instanceof Array || val instanceof Object;
}

// ES2015
var isAO = (val) => val instanceof Array || val instanceof Object;

用法: isAO({}) 将返回trueisAO('{}') 将返回false


7
请注意,由于null可以通过此验证,因此需要小心。 - Farzad Yousefzadeh
2
return !!(JSON.parse(str) && str); 应该阻止空值。我会用这段代码更新答案。 - Machado
1
这是最好的答案,因为它还允许您检查JSON是否已经被“对象化”,从而不会通过parse()测试,导致WTF。 - not2qubit
isJSON('"saddf"')返回true,你觉得怎么样? - Maulik Pipaliya Joyy

43

这是我的工作代码:

function IsJsonString(str) {
  try {
    var json = JSON.parse(str);
    return (typeof json === 'object');
  } catch (e) {
    return false;
  }
}

3
IsJsonString(null); //返回true。可以通过比较typeof str === 'string'来修复。 - gramcha
1
null 表示一个 object 的空值,所以从我的角度来看这看起来不错... 它可能不适用于您的特定情况,但它就是它。 - HellBaby
IsJsonString('{aa:33}') 返回 false。 - Maulik Pipaliya Joyy

37

我使用了一种非常简单的方法来检查字符串是否为有效的JSON。

function testJSON(text){
    if (typeof text!=="string"){
        return false;
    }
    try{
        var json = JSON.parse(text);
        return (typeof json === 'object');
    }
    catch (error){
        return false;
    }
}

有效JSON字符串的结果:

var input='["foo","bar",{"foo":"bar"}]';
testJSON(input); // returns true;

一个简单字符串的结果;

var input='This is not a JSON string.';
testJSON(input); // returns false;

使用对象的结果:

var input={};
testJSON(input); // returns false;

空输入的结果:

var input=null;
testJSON(input); // returns false;

最后一个返回false,因为null类型的变量是object。

这总是有效的。:)


1
JSON.parse(null),JSON.parse("false") 不会抛出错误,可能还有更多的例子。 - klodoma
1
是的,你说得对,我忘记检查输入是否为字符串了。如果我这样做,这个方法在输入null时会返回false。但是"false"输入是一个有效的JSON字符串。它将被解析为boolean (false)。现在我修改代码使其更准确。 - kukko
这将验证 { a: 1, a: 2 } 为有效。有什么想法可以使其验证为假吗? - Alfonso Tienda

21

在prototypeJS中,我们有一个方法isJSON。你可以尝试一下。甚至json也可能有帮助。

"something".isJSON();
// -> false
"\"something\"".isJSON();
// -> true
"{ foo: 42 }".isJSON();
// -> false
"{ \"foo\": 42 }".isJSON();
// -> true

11
谢谢,但我认为使用原型库来做这件事有点过头了。 - Chi Chan
4
你提供了四个例子,但只有三个结果。"{ foo: 42 }".isJSON()的结果是什么?如果像我假设的那样是false(结果应该遵循函数文档),那么好问题是,为什么它是false?"{ foo: 42 }"似乎是完全有效的JSON。 - trejder
4
很抱歉,JSON规范要求使用带引号的键名。 - mikermcneil
4
"2002-12-15" 是一个合法的 JSON 字符串,使用 isJSON 函数返回结果为 true;但是,如果使用 JSON.parse("2002-12-15") 则会抛出错误。请注意,翻译后的内容意思应与原文相同,且不包含解释或其他额外信息。 - ychaouche
4
我认为更好的答案是将该函数从原型库中提取出来并放置在这里。特别是因为http://api.prototypejs.org/language/string/prototype/isjson/已经404。 - jcollum

9
这里还有Typescript版本:
JSONTryParse(input: any) {
    try {
        //check if the string exists
        if (input) {
            var o = JSON.parse(input);

            //validate the result too
            if (o && o.constructor === Object) {
                return o;
            }
        }
    }
    catch (e: any) {
    }

    return false;
};

1
这对我有效,只需添加函数JSONTryParse(input: any) {.. - Bitfinicon

8

我来晚了。这是我最终采取的做法。 使用快速正则表达式预检可大幅提高性能。

if(/^\s*(\{|\[)/.test(str)){
    try{
        JSON.parse(str)
        // do something here, or return obj/true
    }catch(e){
        //  do nothing or return false
    }
}

正则表达式将检查字符串是否以[{开头。这将消除大多数错误情况(但不是全部)。以下是一个快速的性能测试https://jsbench.me/awl6fgn8jb/1

最坏情况下,这可能比直接使用try慢10-15%,最坏情况是所有字符串都是有效的JSON字符串。

最好情况下,这比纯try快99%,最好情况是所有字符串都是非有效的JSON。

这仅寻找解析为对象或数组的字符串。请注意,像“true”这样的字符串化js-primitive值是有效的JSON字符串,出于简单起见,我故意忽略了它们。对于全面的预检,请根据您的用例添加其他检查。


1
这是一个同时验证和解析的最佳答案。我会在初始if语句中添加一个"else return false"。最佳答案! - Thanasis
1
上面的正则表达式排除了一些“假阳性”字符串:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#using_json.parse - LucianDex

8
  • isValidJsonString - 检查有效的JSON字符串

  • JSON数据类型 - 字符串、数字、对象(JSON对象)、数组、布尔值、null (https://www.json.org/json-en.html)

  • Javascript中假值 - false, 0, -0, 0n, "", null, undefined, NaN - (https://developer.mozilla.org/en-US/docs/Glossary/Falsy)

  • JSON.parse

    • 对于数字、布尔值、null和有效的JSON字符串,JSON.parse能够正常工作且不会引发任何错误,请参考下面的示例:

      • JSON.parse(2) // 2
      • JSON.parse(null) // null
      • JSON.parse(true) // true
      • JSON.parse('{"name":"jhamman"}') // {name: "jhamman"}
      • JSON.parse('[1,2,3]') // [1, 2, 3]
    • 在解析undefined、对象、数组等时会报错,请参考下面的示例:

      • 它会产生Uncaught SyntaxError: Unexpected end of JSON input的错误,请参考下面的示例
      • JSON.parse({})
      • JSON.parse([])
      • JSON.parse(undefined)
      • JSON.parse("jack")
function isValidJsonString(jsonString){
    
    if(!(jsonString && typeof jsonString === "string")){
        return false;
    }

    try{
       JSON.parse(jsonString);
       return true;
    }catch(error){
        return false;
    }

}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接