it-roy-ru.com

Как проверить, является ли строка JSON или нет?

У меня есть простой вызов AJAX, и сервер вернет либо строку JSON с полезными данными, либо строку сообщения об ошибке, созданную функцией PHP mysql_error(). Как я могу проверить, являются ли эти данные строкой JSON или сообщением об ошибке. 

Было бы хорошо использовать функцию с именем isJSON так же, как вы можете использовать функцию instanceof, чтобы проверить, является ли что-то массивом.

Это то, что я хочу:

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

Используйте JSON.parse

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

Этот код 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

42
kubosho_

Если сервер отвечает JSON, то он будет иметь тип содержимого application/json, если он отвечает простым текстовым сообщением, то он должен иметь тип содержимого text/plain. Убедитесь, что сервер отвечает с правильным типом содержимого и проверьте это.

21
Quentin

при использовании jQuery $.ajax() ответ будет иметь свойство responseJSON, если ответ был JSON, это можно проверить следующим образом:

if (xhr.hasOwnProperty('responseJSON')) {}
10
rémy

Мне нравится лучший ответ, но если это пустая строка, она возвращает 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;
}
6
Lonnie Price Sr.

Ну ... Это зависит от того, как вы получаете ваши данные. Я думаю, что сервер отвечает форматированной JSON-строкой (Используя json_encode () в PHP, например). Если вы используете публикацию 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',
});
5
Lucas Batistussi

Вероятно, есть тесты, которые вы можете сделать, например, если вы знаете, что возвращаемый JSON всегда будет окружен { и }, тогда вы можете проверить эти символы или каким-нибудь другим хакерским методом. Или вы можете использовать библиотеку json.org JS, чтобы попытаться проанализировать ее и проверить, успешно ли это выполнено.

Однако я бы предложил другой подход. Ваш скрипт PHP в настоящее время возвращает JSON, если вызов успешен, но что-то еще, если это не так. Почему бы всегда не возвращать JSON?

Например.

Успешный звонок:

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

Ошибочный вызов:

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

Это значительно упростит написание JS на стороне клиента - все, что вам нужно сделать, это проверить элемент «status» и действия соответственно.

4
mdm
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 код.

3
ZER0

Я использую только 2 строки, чтобы выполнить это:

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

Это все!

Но имейте в виду, что есть 2 ловушки:
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
2
efkan

Давайте повторим это (для 2018+).

Аргумент: такие значения, как true, false, null, являются действительными JSON (?) 

FACT: да и нет! Эти примитивные значения являются JSON-parsable, но они не являются правильно сформированными структурами JSON. JSONспецификация указывает, что JSON построен на двух структурах: совокупности пары имя/значение (объект) или упорядоченном списке значений (массив). 

Аргумент: обработка исключений не должна использоваться для выполнения чего-то ожидаемого.
(Это комментарий, у которого более 25 голосов!)

FACT: нет! Определенно законно использовать try/catch, особенно в таком случае. В противном случае вам нужно будет выполнить множество операций анализа строк, таких как операции токенизации/регулярного выражения; который имел бы ужасную производительность.

hasJsonStructure()

Это полезно, если ваша цель состоит в том, чтобы проверить, имеют ли некоторые данные/текст правильный формат обмена JSON.

function hasJsonStructure(str) {
    if (typeof str !== 'string') return false;
    try {
        const result = JSON.parse(str);
        return Object.prototype.toString.call(result) === '[object Object]' 
            || Array.isArray(result);
    } 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);
}
2
Onur Yıldırım

Вы можете попробовать расшифровать его и поймать исключение (native или 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
James Sumners

Все строки 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

0
carlin.scott

Я предлагаю в Режим TypeScript:

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