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

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

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

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

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

Ответ 1

Использовать JSON.parse

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

Ответ 2

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

Ответ 3

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

Ответ 4

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

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

Ответ 5

Напомним это (для 2019+).

Аргумент: допустимы такие значения, как true, false, null JSON (?)

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

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

ФАКТ: нет! Определенно законно использовать 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);
}

Ответ 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;
}

Ответ 7

Ну... Это зависит от того, как вы получаете свои данные. Я думаю, что сервер отвечает с помощью JSON string (используя 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',
});

Ответ 8

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

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

например.

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

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

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

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

Это упростит запись вашей клиентской стороны JS - все, что вам нужно сделать, это проверить член "статус" и действовать соответственно.

Ответ 9

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.

Ответ 10

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

Ответ 11

Я использую только 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

Ответ 12

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

Ответ 13

Чтобы создать первый ответ, вместо кода копирования вы можете импортировать этот json-validator с открытым исходным кодом для проверки строки json.

Вот пример использования:

const vaildateJson = require('bit/global/json-validator');
vaildateJson(jsonStr).catch(err => console.log(err))

Ответ 14

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

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

Ответ 15

В дополнение к предыдущим ответам, в случае необходимости проверки формата 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

Ответ 16

Приведенные выше ответы вполне приемлемы, но 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);