[英]How to test if a string is JSON or not?
我有一個簡單的 AJAX 調用,服務器將返回包含有用數據的 JSON 字符串或由 PHP function mysql_error()
生成的錯誤消息字符串。 如何測試此數據是 JSON 字符串還是錯誤消息。
使用名為isJSON
的 function 會很好,就像您可以使用 function instanceof
來測試某物是否為數組一樣。
這就是我要的:
if (isJSON(data)){
//do some data stuff
}else{
//report the error
alert(data);
}
使用 JSON.parse
function isJson(str) {
try {
JSON.parse(str);
} catch (e) {
return false;
}
return true;
}
此代碼是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;
}
測試結果:
讓我們回顧一下(2019+)。
參數:
true
、false
、null
是有效的 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);
}
如果服務器用 JSON 響應,那么它會有一個application/json
內容類型,如果它用純文本消息響應,那么它應該有一個text/plain
內容類型。 確保服務器以正確的內容類型響應並測試它。
使用jQuery $.ajax()
,如果響應是 JSON,則響應將具有responseJSON
屬性,可以這樣測試:
if (xhr.hasOwnProperty('responseJSON')) {}
var parsedData;
try {
parsedData = JSON.parse(data)
} catch (e) {
// is not a valid JSON string
}
但是,我會建議您,您的 http 調用/服務應始終以相同格式返回數據。 因此,如果您有錯誤,那么您應該有一個包含此錯誤的 JSON 對象:
{"error" : { "code" : 123, "message" : "Foo not supported" } }
並且可能使用 5xx 代碼以及 HTTP 狀態。
我喜歡最佳答案,但如果它是空字符串,則返回 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;
}
我只使用 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 格式的字符串進行響應(例如,在 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 總是會被{
和}
包圍,那么您可以測試這些字符或其他一些hacky 方法。 或者你可以使用json.org JS 庫來嘗試解析它並測試它是否成功。
但是,我建議采用不同的方法。 如果調用成功,您的 PHP 腳本當前返回 JSON,否則返回其他內容。 為什么不總是返回 JSON?
例如
調用成功:
{ "status": "success", "data": [ <your data here> ] }
錯誤調用:
{ "status": "error", "error": "Database not found" }
這將使編寫您的客戶端 JS 變得更加容易——您所要做的就是檢查“狀態”成員並相應地采取行動。
這是對 Bourne 的回答進行了一些小的修改的代碼。 由於 JSON.parse(number) 工作正常,沒有任何異常,所以添加了 isNaN。
function isJson(str) {
try {
JSON.parse(str);
} catch (e) {
return false;
}
return isNaN(str);
}
所有 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
我使用了這個(混合了不同的答案,但無論如何):
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('"\?"'))
)
為了避免所有非對象 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
}
}
代碼說明
為什么不使用 hasJsonStructure() 答案?
依賴toString()
不是一個好主意。 這是因為不同的 JavaScript 引擎可能返回不同的字符串表示。 通常,依賴於此的方法可能會在不同的環境中失敗,或者如果引擎更改字符串結果,則以后可能會失敗
為什么捕獲異常不是黑客攻擊?
有人提出,捕捉異常來確定某事的有效性從來都不是正確的方法。 這通常是很好的建議,但並非總是如此。 在這種情況下,異常捕獲可能是最佳途徑,因為它依賴於 JavaScript 引擎對 JSON 數據進行驗證的實現。
依靠JS引擎提供以下優勢:
當有機會依靠 JavaScript 引擎時,我建議這樣做。 在這種情況下尤其如此。 盡管捕獲異常可能會讓人感覺很棘手,但您實際上只是在處理來自外部方法的兩種可能的返回狀態。
我建議在打字稿模式下:
export function stringify(data: any): string {
try {
return JSON.stringify(data)
} catch (e) {
return 'NOT_STRINGIFIABLE!'
}
}
您可以嘗試以下方法,因為它還可以驗證數字、空值、字符串,但上面標記的答案無法正常工作,它只是對上述功能的修復:
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;
};
歡迎 :)
數字和boolean值在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;
}
export function isJsonString(value) { try { return typeof JSON.parse(value) === 'object'; } catch (e) { return 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
上面的答案是相當不錯的,但JSON.parse據說是昂貴的,所以你很可能只想保留解析后的數據,而不是再次解析。
function isJson(str) {
if (typeof str !== "string" || `${str}`.length === 0) return [false, str];
let json = "";
let isValid = false;
try {
json = JSON.parse(str);
isValid = true;
} catch (e) {
isValid = false
}
if (!json || typeof json !== "object") isValid = false;
return [isValid, json]
};
//Usage
const [isValid, json] = isJson("[\"abc\", \"123\"]");
if(isValid) console.log(json);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.