如何测试字符串是否为JSON?


191

我有一个简单的AJAX调用,服务器将返回包含有用数据的JSON字符串或PHP函数产生的错误消息字符串mysql_error()。如何测试此数据是JSON字符串还是错误消息。

最好使用一个称为的函数isJSON,就像您可以使用该函数instanceof来测试某物是否为数组一样。

这就是我要的:

if (isJSON(data)){
    //do some data stuff
}else{
    //report the error
    alert(data);
}

也许使用eval()如果返回undefined则不是JSON
MatuDuke 2012年

4
这已经在这里解决:stackoverflow.com/questions/3710204/...
Reinard

2
谢谢大家,对不起,我之前没有找到其他帖子。
jeffery_the_wind 2012年

1
从技术上讲,这不是3710204的伪装,因为有人询问它是否是有效的json,这比传递的json高得多。
carlin.scott 2016年

Answers:


318

使用JSON.parse

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

53
异常处理不应用于执行预期的操作。
luisZavaleta 2015年

44
JSON.parse(1234)OR JSON.parse(0)OR JSON.parse(false)OR JSON.parse(null)all将不会引发Exception并将返回true!不要使用此答案
Zalaboza 2015年

19
@Zalaboza 12340false,和null都是有效的JSON值。如果您想要一个谓词来测试JSON是否代表一个对象,则需要做更多的事情。
Michael Lang

20
JSON.parse进行了大量计算以解析该字符串,如果成功,则为您提供json对象,但是您正在丢弃某些用户可能想要使用的结果。那似乎不好。我将改为return {value: JSON.parse(str), valid: true};在catch块return {value: str, valid: false};中将函数名称更改为tryParse()
Nawaz

7
@luisZavaleta,那么您对方法的建议是什么
PirateApp

79

此代码是JSON.parse(1234)or JSON.parse(0)JSON.parse(false)or JSON.parse(null)all将返回true。

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

所以我以这种方式重写了代码:

function isJson(item) {
    item = typeof item !== "string"
        ? JSON.stringify(item)
        : item;

    try {
        item = JSON.parse(item);
    } catch (e) {
        return false;
    }

    if (typeof item === "object" && item !== null) {
        return true;
    }

    return false;
}

测试结果:

isJson测试结果


4
干得好!您的最后一个if语句可以简化为简单的return语句,例如:return (typeof suspect === "object" && suspect !== null);
Nebulosar

37

让我们回顾一下(2019年以上)。

参数:值,例如truefalsenull是有效JSON(?)

事实:这些原始值是JSON可解析的,但它们不是格式正确的JSON结构JSON 规范指示JSON建立在两个结构上:名称/值对(对象)或值的有序列表(数组)的集合。

参数:异常处理不应用于执行预期的操作。
(此评论有25个以上的赞誉!)

事实:不!使用try / catch绝对合法,尤其是在这种情况下。否则,您需要做很多字符串分析工作,例如标记化/正则表达式操作。会有糟糕的表现

hasJsonStructure()

如果您的目标是检查某些数据/文本是否具有正确的JSON交换格式,这将很有用。

function hasJsonStructure(str) {
    if (typeof str !== 'string') return false;
    try {
        const result = JSON.parse(str);
        const type = Object.prototype.toString.call(result);
        return type === '[object Object]' 
            || type === '[object Array]';
    } catch (err) {
        return false;
    }
}

用法:

hasJsonStructure('true')             // —» false
hasJsonStructure('{"x":true}')       // —» true
hasJsonStructure('[1, false, null]') // —» true

safeJsonParse()

如果在将某些数据解析为JavaScript值时要小心一点,这将很有用。

function safeJsonParse(str) {
    try {
        return [null, JSON.parse(str)];
    } catch (err) {
        return [err];
    }
}

用法:

const [err, result] = safeJsonParse('[Invalid JSON}');
if (err) {
    console.log('Failed to parse JSON: ' + err.message);
} else {
    console.log(result);
}

1
您链接到JSON Spec时,表示以下内容:“ JSON文本是由符合JSON值语法的Unicode代码点形成的令牌序列。” 和“ JSON值可以是对象,数组,数字,字符串,true,false或null。” -如何得出一个结论,即JSON只能是根级别的对象或数组?我在规范中看不到这一点,也没有任何关于“格式正确的JSON结构”的信息
Relequestual,

读第二段与开始“JSON是建立在两个结构......” @ json.org或第4和第5段ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
厄尼尔耶尔德勒姆

json.org仅提供信息。阅读您链接到的规范不支持您的建议。该规范提到RFC 8259作为最新的RFC。看一看仅包含值工具的有效JSON tex的示例。ietf.org/ html / rfc8259#section - 13 -RFC 8259旨在解决可能的歧义和混乱,就像这样。
Relequestual '19

再次阅读答案。我说的是诸如基元之类的值(即RFC示例中的文本值)不是JSON“结构”。没有歧义。您可以将它们解析为JSON,这样做是有效的。但是它们不是结构化数据。JSON主要是作为一种交换格式发明的,该交换格式用于结构化数据,可以是对象或数组。
OnurYıldırım19年

1
好,所以我认为我们同意。根据规范,基元是有效的JSON,但不是“结构”。没关系。但是,您说的是“参数:true,false,null之类的值是有效的JSON(?)。事实:是,不是!” -实际上是根据规范的ARE有效JSON。关于它们是否有用的意见与该事实无关。
Relequestual,

20

如果服务器以JSON响应,则它将具有application/json内容类型;如果服务器以纯文本消息响应,则应具有text/plain内容类型。确保服务器使用正确的内容类型进行响应并进行测试。


4
这是错误的,还有许多其他与json兼容的媒体类型。此外overrideMimeType可以覆盖内容类型标头。
6

13

当使用jQuery $.ajax()响应时,responseJSON如果响应是JSON,则将具有该属性,可以这样检查:

if (xhr.hasOwnProperty('responseJSON')) {}

2
我怀疑这真的是大多数人都在寻找的答案,甚至可能是OP
Kirby 2015年

这比使用try catch块要优雅得多
Anurag Sinha

6

我喜欢最佳答案,但是如果它是一个空字符串,则返回true。因此,这里有一个解决方法:

function isJSON(MyTestStr){
    try {
        var MyJSON = JSON.stringify(MyTestStr);
        var json = JSON.parse(MyJSON);
        if(typeof(MyTestStr) == 'string')
            if(MyTestStr.length == 0)
                return false;
    }
    catch(e){
        return false;
    }
    return true;
}

不使用var json?还是只是为了捕捉错误?
stackdave

5
var parsedData;

try {
    parsedData = JSON.parse(data)
} catch (e) {
    // is not a valid JSON string
}

但是,我建议您http呼叫/服务应始终返回相同格式的数据。因此,如果发生错误,则应该包含包装此错误的JSON对象:

{"error" : { "code" : 123, "message" : "Foo not supported" } } 

甚至可以使用HTTP状态的5xx代码。


5

好吧...这取决于您接收数据的方式。我认为服务器正在以JSON格式的字符串响应(例如在PHP中使用json_encode())。如果您使用的是JQuery发布,并将响应数据设置为JSON格式,并且它是格式错误的JSON,则会产生错误:

$.ajax({
  type: 'POST',
  url: 'test2.php',
  data: "data",
  success: function (response){

        //Supposing x is a JSON property...
        alert(response.x);

  },
  dataType: 'json',
  //Invalid JSON
  error: function (){ alert("error!"); }
});

但是,如果您将类型响应用作文本,则需要使用$ .parseJSON。根据jquery网站的说法:“传递格式错误的JSON字符串可能会导致引发异常”。因此,您的代码将是:

$.ajax({
  type: 'POST',
  url: 'test2.php',
  data: "data",
  success: function (response){

        try {
            parsedData = JSON.parse(response);
        } catch (e) {
            // is not a valid JSON string
        }

  },
  dataType: 'text',
});

除非,当然,除非您在上面的示例中尝试解析错误函数中的错误文本,并且不确定是否为JSON ...
Kirby

好的答案,尽管如果response是空的,它将转到success:'(
Henrik Petterson

4

可能有一些测试可以做,例如,如果您知道返回的JSON总是会被包围{}那么您可以测试这些字符或其他一些hacky方法。或者您可以使用json.org JS库尝试解析它并测试它是否成功。

但是,我建议采用另一种方法。如果调用成功,您的PHP脚本当前返回JSON,否则返回JSON。为什么不总是返回JSON?

例如

成功呼叫:

{ "status": "success", "data": [ <your data here> ] }

错误呼叫:

{ "status": "error", "error": "Database not found" }

这将使编写客户端JS变得更加容易-您要做的就是检查“状态”成员并相应地执行操作。


4

我仅用两行来执行该操作:

var isValidJSON = true;
try { JSON.parse(jsonString) } catch { isValidJSON = false }

就这样!

但是请记住有两个陷阱:
1. JSON.parse(null)返回null
2.可以使用JSON.parse()method 解析任何数字或字符串。
   JSON.parse("5")退货5
   JSON.parse(5)退货5

让我们来看看代码:

// TEST 1
var data = '{ "a": 1 }'

// Avoiding 'null' trap! Null is confirmed as JSON.
var isValidJSON = data ? true : false
try { JSON.parse(data) } catch(e) { isValidJSON = false }

console.log("data isValidJSON: ", isValidJSON);
console.log("data isJSONArray: ", isValidJSON && JSON.parse(data).length ? true : false);

Console outputs:
data isValidJSON:  true
data isJSONArray:  false


// TEST 2
var data2 = '[{ "b": 2 }]'

var isValidJSON = data ? true : false
try { JSON.parse(data2) } catch(e) { isValidJSON = false }

console.log("data2 isValidJSON: ", isValidJSON);
console.log("data2 isJSONArray: ", isValidJSON && JSON.parse(data2).length ? true : false);

Console outputs:
data2 isValidJSON:  true
data2 isJSONArray:  true


// TEST 3
var data3 = '[{ 2 }]'

var isValidJSON = data ? true : false
try { JSON.parse(data3) } catch(e) { isValidJSON = false }

console.log("data3 isValidJSON: ", isValidJSON);
console.log("data3 isJSONArray: ", isValidJSON && JSON.parse(data3).length ? true : false);

Console outputs:
data3 isValidJSON:  false
data3 isJSONArray:  false


// TEST 4
var data4 = '2'

var isValidJSON = data ? true : false
try { JSON.parse(data4) } catch(e) { isValidJSON = false }

console.log("data4 isValidJSON: ", isValidJSON);
console.log("data4 isJSONArray: ", isValidJSON && JSON.parse(data4).length ? true : false);


Console outputs:
data4 isValidJSON:  true
data4 isJSONArray:  false


// TEST 5
var data5 = ''

var isValidJSON = data ? true : false
try { JSON.parse(data5) } catch(e) { isValidJSON = false }

console.log("data5 isValidJSON: ", isValidJSON);
console.log("data5 isJSONArray: ", isValidJSON && JSON.parse(data5).length ? true : false);


Console outputs:
data5 isValidJSON:  false
data5 isJSONArray:  false

// TEST 6
var data6; // undefined

var isValidJSON = data ? true : false
try { JSON.parse(data6) } catch(e) { isValidJSON = false }

console.log("data6 isValidJSON: ", isValidJSON);
console.log("data6 isJSONArray: ", isValidJSON && JSON.parse(data6).length ? true : false);

Console outputs:
data6 isValidJSON:  false
data6 isJSONArray:  false

我在jsfiddle.net/fatmonk/gpn4eyav上为此答案创建了一个小提琴,其中还包括添加您自己的用户测试数据的选项。这对我来说似乎是一个好的库函数的基础,但是我想更多地了解为什么Test 1不是有效的JSON数组。
Fat Monk'1

因为必须使用[和来指定数组]。例如,[1, 2, 3]是一个数字数组。["a", "b", "c"]是一个字符串数组。并且[{"a":1}, {"b":2}]是一个JSON数组。您的jsfiddle工作似乎非常有用!
efkan

就如此容易?!因此,测试1是JSON对象,而测试2是由单个JSON对象元素组成的JSON数组。我理解正确吗?
Fat Monk'1

标记为可能与此重复的问题(stackoverflow.com/questions/3710204/…)询问如何不使用try / catch来实现此目标,因此,我花了很多力气来尝试实现该目标。分支位于jsfiddle.net/fatmonk/827jsuvr,并且可以与上述所有测试一起使用,但Test 3的错误在上JSON.parse。谁能建议不使用try避免该错误?
Fat Monk

jsfiddle由于测试3没有有效的JSON表达式,因此您的应用程序将引发错误。因此,try-catch必须使用a来捕获该错误并评估任何错误,因为在像上面的Test 3一样进行解析时,表达式不是JSON:try { JSON.parse(data3) } catch(e) { isValidJSON = false }
efkan

2

您可以尝试将其解码并捕获 异常(本机或json2.js):

try {
  newObj = JSON.parse(myJsonString);
} catch (e) {
  console.log('Not JSON');
}

但是,我建议使响应始终是有效的JSON。如果您从MySQL查询返回错误,只需将错误返回JSON:

{"error":"The MySQL error string."}

然后:

if (myParsedJSON.error) {
  console.log('An error occurred: ' + myParsedJSON.error);
}

2

警告:对于依赖的方法JSON.parse-数组和引号引起来的字符串也将通过(即console.log(JSON.parse('[3]'), JSON.parse('"\uD800"'))

为了避免使用所有非对象JSON原语(布尔,空,数组,数字,字符串),建议使用以下命令:

/* Validate a possible object ie. o = { "a": 2 } */
const isJSONObject = (o) => 
  !!o && (typeof o === 'object') && !Array.isArray(o) && 
  (() => { try { return Boolean(JSON.stringify(o)); } catch { return false } })()

/* Validate a possible JSON object represented as string ie. s = '{ "a": 3 }' */
function isJSONObjectString(s) {
    try {
        const o = JSON.parse(s);
        return !!o && (typeof o === 'object') && !Array.isArray(o)
    } catch {
        return false
    }
}

代码说明

  • !! o-不虚假(不包括null,其注册为typeof'object')
  • (typeof o ==='对象') -排除布尔值,数字和字符串
  • !Array.isArray(o)-排除数组(注册为typeof'object')
  • 尝试... JSON.stringify / JSON.parse-要求JavaScript引擎确定是否有效的JSON

为什么不使用hasJsonStructure()答案?

依靠 toString()不是一个好主意。这是因为不同的JavaScript引擎可能返回不同的字符串表示形式。通常,依赖此方法的方法可能在不同的环境中失败,或者如果引擎更改了字符串结果,则以后可能会失败

为什么捕获异常不是黑客?

人们提出,捕获异常来确定某项内容的有效性绝不是正确的方法。通常这是一个很好的建议,但并非总是如此。在这种情况下,捕获异常可能是最好的方法,因为它依赖JavaScript引擎对JSON数据进行验证的实现。

依靠JS引擎具有以下优点:

  1. 随着JSON规范的更改,更全面,不断更新
  2. 可能运行得更快(因为它是较低级别的代码)

如果有机会依靠JavaScript引擎,我建议您这样做。在这种情况下尤其如此。虽然可能会感觉捕获异常麻烦,但实际上您只是在处理来自外部方法的两个可能的返回状态。


1

这是对Bourne的答案进行一些小的修改的代码。由于JSON.parse(number)正常工作,没有任何异常,因此添加了isNaN。

function isJson(str) {
    try {
        JSON.parse(str);
    } catch (e) {
        return false;
    }
    return isNaN(str);
}

0

所有json字符串均以“ {”或“ [”开头,并以相应的“}”或“]”结尾,因此只需检查一下即可。

这是Angular.js的工作方式:

var JSON_START = /^\[|^\{(?!\{)/;
var JSON_ENDS = {
  '[': /]$/,
  '{': /}$/
};

function isJsonLike(str) {
    var jsonStart = str.match(JSON_START);
    return jsonStart && JSON_ENDS[jsonStart[0]].test(str);
}

https://github.com/angular/angular.js/blob/v1.6.x/src/ng/http.js


@DukeDougal护理需要澄清吗?有时人们以'['开头他们的json,但这并不常见。
carlin.scott

1
您需要对其进行解析以使用有效的JSON。如果它是无效的JSON,则它不是JSON。问题是“如何分辨字符串是否为JSON?”。按照您的方法,这将是JSON {fibble-而且实际上不是JSON。还要考虑数字1本身的情况-这是有效的JSON。
杜加尔(Dougal)公爵

1
“如果它是无效的JSON,则它不是JSON”。必须使用“有效”一词的事实表明,您不仅要对json进行限定,而且要添加一个限定条件。问题只是“是json吗”,我的代码示例完美地回答了这个问题,而无需承担其他要求。
carlin.scott

如果您使用的是某些模板系统,并且有类似的东西{ someValue }会自动通过验证,那就不好了。
ncubica

@ncubica,因此您将模板用于除json之外的其他内容,字符串仅包含使用花括号的占位符,并且模板引擎无法将占位符替换为真实值?还要记住,就像我已经向Duke解释过的那样,原始问题没有提到验证。他们只想知道它是否看起来像json。
carlin.scott 2016年

0

我建议在打字稿模式下:

export function stringify(data: any): string {
    try {
         return JSON.stringify(data)
    } catch (e) {
         return 'NOT_STRINGIFIABLE!'
    }
}

0

我使用了这个(混合了不同的答案,但是无论如何):

const isJSON = str => {
  if (typeof str === 'string'){
    try {
      JSON.parse(str)
      return true
    } catch(e){
    }
  }
  return false
}



[null, undefined, false, true, [], {}, 
 '', 'asdf', '{}', '[]', "{\"abc\": 2}","{\"abc\": \"2\"}"]
  .map(el => {
      console.log(`[>${el}<] - ${isJSON(el)}`)
})

console.log('-----------------')


0

您可以尝试以下方法,因为它也可以验证数字,空值,字符串,但是上面标记的答案不能正常工作,这只是上述功能的一种解决方法:

function isJson(str) {
  try {
      const obj = JSON.parse(str);
      if (obj && typeof obj === `object`) {
        return true;
      }
    } catch (err) {
      return false;
    }
   return false;
}

-1

除了先前的答案,如果您需要验证“ {}”之类的JSON格式,则可以使用以下代码:

const validateJSON = (str) => {
  try {
    const json = JSON.parse(str);
    if (Object.prototype.toString.call(json).slice(8,-1) !== 'Object') {
      return false;
    }
  } catch (e) {
    return false;
  }
  return true;
}

用法示例:

validateJSON('{}')
true
validateJSON('[]')
false
validateJSON('')
false
validateJSON('2134')
false
validateJSON('{ "Id": 1, "Name": "Coke" }')
true
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.