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

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

使用名为isJSON的函数会很好,就像你可以使用instanceof函数来测试某个东西是否是数组一样。

这就是我想要的:

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

使用JSON.parse

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

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

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

然而,我建议另辟蹊径。如果调用成功,PHP脚本当前返回JSON,如果调用失败,则返回其他内容。为什么总是不返回JSON?

如。

成功的电话:

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

错误的电话:

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

这将使您的客户端JS编写更容易-你所要做的就是检查“status”成员和相应的行为。

var parsedData;


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

但是,我建议你的http call / service应该总是以相同的格式返回一个数据。所以如果你有一个错误,那么你应该有一个JSON对象来包装这个错误:

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

可能还会使用HTTP状态5xx代码。

你可以尝试解码它并捕获异常(本机或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);
}
< p >嗯…这取决于你接收数据的方式。我认为服务器正在响应一个JSON格式 字符串(在PHP中使用json_encode(),例如)。如果你正在使用JQuery post并将响应数据设置为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',
});

我喜欢最好的答案,但如果它是一个空字符串,它返回真。这里有一个解决方案:

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;
}

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

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

此代码为JSON.parse(1234)JSON.parse(0)JSON.parse(false)JSON.parse(null),它们都会返回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测试结果

所有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

我只用了2行代码来执行:

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

这是所有!

但是请记住有两个陷阱 1. JSON.parse(null)返回null
2. 任何数字或字符串都可以用JSON.parse()方法解析 ,,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

除了前面的答案,如果你需要验证一个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

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

论点:诸如truefalsenull这样的值是有效的JSON (?)

事实:这些基元值是JSON-parsable,但不是__abc2。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);
}

我用了这个(有点混合了不同的答案,但不管怎样):

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('-----------------')

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

为了避免所有非对象JSON原语(boolean, null, array, number, string),我建议使用以下方法:

/* 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,它注册为'object'类型)
  • (typeof o === 'object') -排除布尔值,数字和字符串
  • Array.isArray(o) -排除数组(注册为'object'类型的数组)
  • 试一试……JSON。stringify / JSON.parse -要求JavaScript引擎确定是否有效的JSON

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

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

为什么捕获异常不是破解?

有人提出,通过捕获异常来确定某个东西的有效性从来都不是正确的方法。这通常是一个好建议,但也不总是这样。在这种情况下,异常捕获可能是最好的方法,因为它依赖于JavaScript引擎验证JSON数据的实现。

依赖JS引擎提供了以下优势:

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

当有机会依赖JavaScript引擎时,我建议这样做。在这种情况下尤其如此。虽然它可能通过感觉来捕获异常,但实际上你只是在处理外部方法的两种可能返回状态。

这是一个代码,在伯恩的回答中有一些小的修改。 因为JSON.parse(number)工作正常,没有任何异常,所以添加了isNaN.

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

你可以尝试下面的一个,因为它也验证数字,null,字符串,但上面标记的答案不能正常工作,这只是上面函数的修复:

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

我认为像下面的方法应该做的工作,它返回解析的JSON(在有效JSON的情况下),所以你不需要再次调用JSON.parse

const tryParseJSON = (s) => {
if (!s) return false;


try {
var o = JSON.parse(s);
if (o && typeof o === "object") return o;
}
catch (e) { }


return false;
};

如果你不介意lodash

npm i -S lodash

const isPlainObject = require("lodash/isPlainObject"); // cjs
// import {isPlainObject} from "lodash"; // esm
function checkIfJSON(input) {
const inputStr = typeof input === "string" ? input : JSON.stringify(input);
try {
if (isPlainObject(JSON.parse(inputStr))) {
return true;
}
} catch (e) {
return false;
}
}

对我来说,我只是通过2个正返回条件,

第一个条件 -检查两端是否为"{"和“}”;

第二个条件 -检查它是否可以被JSON解析

我是这样做的

const isJsonStringified = (value) => {
try {
const isObject = value.slice(0, 1) === '{' && value.slice(value.length - 1) === '}';
if (typeof value === 'string' && isObject) {
JSON.parse(value);
} else {
return false;
}
} catch (err) {
return false;
}
return true;
};

欢迎:)

数字和布尔值在json .parse()中被接受为有效的json,只需在解析前添加类型验证

function isJson(str) {


if(!isNaN(str) || str.toString() == 'true' || str.toString() == 'false'){
return false;
}


try {


JSON.parse(str);


} catch (e) {


return false;


}


return true;


}