Безопасное превращение строки JSON в объект


1337

Учитывая строку данных JSON, как я могу безопасно превратить эту строку в объект JavaScript?

Очевидно, что я могу сделать это небезопасно с чем-то вроде:

var obj = eval("(" + json + ')');

но это делает меня уязвимым для строки JSON, содержащей другой код, который кажется очень опасным для простой оценки.


77
В большинстве языков eval несет дополнительный риск. Эвал оставляет открытую дверь для использования хакерами. ОДНАКО помните, что все JavaScript работает на клиенте. Ожидать, что это будет изменено хакерами. Они могут ПРОВЕРИТЬ все, что захотят, просто используя консоль. Вы должны построить свою защиту на стороне сервера.
Beachhouse

19
Хорошо, сейчас 2014, и вы никогда не должны использовать его evalдля анализа строки JSON, потому что вы подвергаете свой код «внедрению кода». Используйте JSON.parse(yourString)вместо этого.
Даниэль

Являются ли данные JSON литералом?
Шанечу

@shanechiu: если вы имеете в виду скалярный тип данных, да, это так. Это просто строка с синтаксисом ключ-значение.
0zkr PM

Ответы:


1964

JSON.parse(jsonString) это чистый подход JavaScript, если вы можете гарантировать достаточно современный браузер.


74
Я уверен, что это безопасно для Node.js
Стивен

76
@vsync вы понимаете, что это ЕДИНСТВЕННЫЙ чистый ответ Javascript ... если вы прочитаете описание тега javascript, вы увидите это ... " Если тег для фреймворка / библиотеки также не включен, чистый ответ JavaScript ожидается. ".. Я даю это +1 за то, что я единственный ответ javascript ...
iConnor


12
Если вы работаете с NodeJS, я не смог бы загрузить jQuery просто для анализа jsonString в объект JSON. Так что ответ Джонатана upvote
Энтони

6
По этой ссылке поддерживается IE8 +, хотя там написано:Requires document to be in IE8+ standards mode to work in IE8.
JoshuaDavid

878

Метод jQuery устарел. Используйте этот метод вместо:

let jsonObject = JSON.parse(jsonString);

Исходный ответ с использованием устаревшей функциональности jQuery :

Если вы используете jQuery, просто используйте:

jQuery.parseJSON( jsonString );

Это именно то, что вы ищете (см. Документацию jQuery ).


7
Есть ли причина использовать это поверх JSON.parse ()?
Джон

8
jQuery.parseJSONпо умолчанию используется, JSON.parseесли он существует, поэтому единственная причина использовать это по сравнению с реальной - это если вам нужен запасной вариант для <IE7. В jQuery 1.6 это было изменено: james.padolsey.com/jquery/#v=1.6.0&fn=jQuery.parseJSON
Карл-Йохан Шегрен,

9
Обновление 2016: Начиная с jQuery 3.0, $ .parseJSON устарел, и вместо него следует использовать собственный метод JSON.parse.
jkdev

159

Этот ответ для IE <7, для современных браузеров проверьте ответ Джонатана выше.

Этот ответ устарел, и ответ Джонатана выше ( JSON.parse(jsonString)) теперь является лучшим ответом .

JSON.org имеет парсеры JSON для многих языков, включая четыре различных для JavaScript. Я считаю, что большинство людей считают json2.js своей реализацией.


24
Я бы хотел, чтобы люди перестали голосовать за этот ответ. Он был точным, когда он был опубликован в 2008 году. Просто добавьте новый.
Джон

22
Если ответ сейчас устарел, рассмотрите возможность его обновления.
Сотириос Делиманолис

2
для IE <8 вы должны использовать это.
Mahmoodvcs

74

Используйте простой пример кода в " JSON.parse () ":

var jsontext = '{"firstname":"Jesper","surname":"Aaberg","phone":["555-0100","555-0120"]}';
var contact = JSON.parse(jsontext);

и наоборот:

var str = JSON.stringify(arr);

23

Я не уверен насчет других способов сделать это, но вот как вы это делаете в Prototype (учебник по JSON) .

new Ajax.Request('/some_url', {
  method:'get',
  requestHeaders: {Accept: 'application/json'},
  onSuccess: function(transport){
    var json = transport.responseText.evalJSON(true);
  }
});

Вызов evalJSON()с истиной в качестве аргумента дезинфицирует входящую строку.


22

Это, кажется, проблема:

Ввод, полученный через веб-сокет Ajax и т. Д., И он будет в формате String, но вам необходимо знать, так ли это JSON.parsable. Двойным является то, что, если вы всегда запускаете его JSON.parse, программа МОЖЕТ продолжаться «успешно», но вы все равно увидите ошибку, выданную в консоли с ужасом "Error: unexpected token 'x'".

var data;

try {
  data = JSON.parse(jqxhr.responseText);
} catch (_error) {}

data || (data = {
  message: 'Server error, please retry'
});

NO. Проблема заключается в том, что вы ожидаете JSON-объект и в итоге можете получить что- (function(){ postCookiesToHostileServer(); }());то еще более неприятное в контексте Node.
Яур

Хорошо JSON.parse очищает ввод функций (что в этом случае не помогло бы как его IIF -> объект). Кажется, лучший способ решить эту тему - попробовать / поймать. (См. Правку)
Коди

18

Если вы используете jQuery , вы также можете использовать:

$.getJSON(url, function(data) { });

Тогда вы можете делать такие вещи, как

data.key1.something
data.key1.something_else

и т.п.


Вы используете JQuery, не так ли?
Александр С.

15
$.ajax({
  url: url,
  dataType: 'json',
  data: data,
  success: callback
});

Обратному вызову передаются возвращенные данные, которые будут объектом или массивом JavaScript, как определено структурой JSON, и проанализированы с использованием $.parseJSON()метода.


12

Просто для удовольствия, вот способ использования функции:

 jsonObject = (new Function('return ' + jsonFormatData))()

1
Интересный подход, я не уверен, что использовал бы это с доступным JSON.Parse, но приятно видеть, что кто-то думает вне коробки.

5
Это очень похоже на простое использование evalи не безопасно. : P
Флорри

7
Это имеет все недостатки использования, evalно его сложнее и труднее понять сопровождающим.
Квентин

9

Использование JSON.parse, вероятно, лучший способ.

Вот пример живой демонстрации .

var jsonRes = '{ "students" : [' +
          '{ "firstName":"Michel" , "lastName":"John" ,"age":18},' +
          '{ "firstName":"Richard" , "lastName":"Joe","age":20 },' +
          '{ "firstName":"James" , "lastName":"Henry","age":15 } ]}';
var studentObject = JSON.parse(jsonRes);

9

Самый простой способ с использованием parse()метода:

var response = '{"result":true,"count":1}';
var JsonObject= JSON.parse(response);

Затем вы можете получить значения элементов JSON, например:

var myResponseResult = JsonObject.result;
var myResponseCount = JsonObject.count;

Используя jQuery, как описано в jQuery.parseJSON()документации:

JSON.parse(jsonString);

9

Попробуйте использовать метод с этим объектом данных. например: Data='{result:true,count:1}'

try {
  eval('var obj=' + Data);
  console.log(obj.count);
}
catch(e) {
  console.log(e.message);
}

Этот метод действительно помогает в Nodejs, когда вы работаете с программированием последовательного порта


Это действительно забавно, как люди зациклены на «eval is evil», и они сделают все, чтобы избежать этого, даже переписав всю функциональность eval ..
diynevala

Является ли консенсус этот трюк безопасным методом превращения строки в объект JSON? Я мог бы использовать это, так как не требуется дополнительный импорт JS.
Whome

1
ЛЮБОЙ подход, использующий evalили Functionв равной степени уязвимый
Слай

undefined; function bye() {...} bye();
Сальвионер

5

Я нашел «лучший» способ:

В CoffeeScript:

try data = JSON.parse(jqxhr.responseText)
data ||= { message: 'Server error, please retry' }

В Javascript:

var data;

try {
  data = JSON.parse(jqxhr.responseText);
} catch (_error) {}

data || (data = {
  message: 'Server error, please retry'
});

4

Разбор JSON - это всегда боль. Если ввод не такой, как ожидалось, он выдает ошибку и вылетает, что вы делаете.

Вы можете использовать следующую крошечную функцию для безопасного анализа вашего ввода. Он всегда поворачивает объект, даже если ввод недействителен или уже является объектом, что лучше для большинства случаев:

JSON.safeParse = function (input, def) {
  // Convert null to empty object
  if (!input) {
    return def || {};
  } else if (Object.prototype.toString.call(input) === '[object Object]') {
    return input;
  }
  try {
    return JSON.parse(input);
  } catch (e) {
    return def || {};
  }
};

Object.prototype.toString.call(input) === '[object Object]'должно быть typeof input === 'object'ИМО
Серж К.

typeof input возвращает объект для нуля и массивов. Так что это не безопасный способ сделать это.
Тахсин Туркоз

Вы уже рассмотрели этот nullслучай раньше, и массив является объектом. Если вы хотите проверить это, вы можете использовать instanceof. Более того, если вы дадите этой функции значение an Array, она будет ловить и return defтогда, когда она могла бы вернуть совершенно точный массив.
Серж К.

Мой комментарий был о здравом смысле при ловле предметов. Моя функция может иметь несколько предупреждений, но использование ввода typeof не является предпочтительным способом обнаружения объектов в целом.
Tahsin Turkoz

IMO, здравый смысл не использует toString()метод, чтобы проверить, является ли переменная объектом или нет. Смотрите AngularJS , jQuery , Underscore или даже разработчиков
Серж К.


3

Если у нас есть такая строка:

"{\"status\":1,\"token\":\"65b4352b2dfc4957a09add0ce5714059\"}"

тогда мы можем просто использовать JSON.parseдважды, чтобы преобразовать эту строку в объект JSON:

var sampleString = "{\"status\":1,\"token\":\"65b4352b2dfc4957a09add0ce5714059\"}"
var jsonString= JSON.parse(sampleString)
var jsonObject= JSON.parse(jsonString)

И мы можем извлечь значения из объекта JSON, используя:

// instead of last JSON.parse:
var { status, token } = JSON.parse(jsonString);

Результатом будет:

status = 1 and token = 65b4352b2dfc4957a09add0ce5714059

3

JSON.parse() преобразует любую строку JSON, переданную в функцию, в объект JSON.

Чтобы лучше это понять, нажмите, F12чтобы открыть «Проверка элемента» в браузере и перейти к консоли, чтобы написать следующие команды:

var response = '{"result":true,"count":1}'; //sample json object(string form)
JSON.parse(response); //converts passed string to JSON Object.

Теперь запустите команду:

console.log(JSON.parse(response));

Вы получите вывод как объект {result: true, count: 1} .

Чтобы использовать этот объект, вы можете присвоить его переменной, возможно, obj :

var obj = JSON.parse(response);

Используя obj и точку (. оператор ), вы можете получить доступ к свойствам объекта JSON.

Попробуйте запустить команду:

console.log(obj.result);

3

Официальная документация :

JSON.parse()Метод анализирует строку JSON, конструируя значение JavaScript или объект , описанный в строке. reviverМожет быть предоставлена необязательная функция для выполнения преобразования результирующего объекта перед его возвращением.

Синтаксис:

JSON.parse(text[, reviver])

Параметры:

text : Строка для анализа в формате JSON. См. Объект JSON для описания синтаксиса JSON.

reviver (optional) : Если функция, это предписывает, как значение, первоначально произведенное синтаксическим анализом, преобразовано, прежде чем будет возвращено.

Возвращаемое значение

Объект, соответствующий заданному тексту JSON.

Исключения

Выдает исключение SyntaxError, если строка для анализа недопустима в формате JSON.



2

Синтаксически проанализируйте строку JSON JSON.parse(), и данные станут объектом JavaScript:

JSON.parse(jsonString)

Здесь JSON представляет для обработки набора данных JSON.

Представьте, что мы получили этот текст с веб-сервера:

'{ "name":"John", "age":30, "city":"New York"}'

Для анализа в объект JSON:

var obj = JSON.parse('{ "name":"John", "age":30, "city":"New York"}'); 

Вот objсоответствующий объект JSON, который выглядит следующим образом:

{ "name":"John", "age":30, "city":"New York"}

Чтобы получить значение, используйте .оператор:

obj.name // John
obj.age //30

Преобразуйте объект JavaScript в строку с помощью JSON.stringify().


1

Просто на разбор обложки для разных типов ввода

Выполните синтаксический анализ данных с помощью JSON.parse (), и данные станут объектом JavaScript.

var obj = JSON.parse('{ "name":"John", "age":30, "city":"New York"}');

При использовании JSON.parse () в JSON, производном от массива, метод возвращает массив JavaScript вместо объекта JavaScript.

var myArr = JSON.parse(this.responseText);
console.log(myArr[0]);

Объекты даты не допускаются в JSON. Для Даты сделать что-то вроде этого

var text = '{ "name":"John", "birth":"1986-12-14", "city":"New York"}';
var obj = JSON.parse(text);
obj.birth = new Date(obj.birth);

Функции не допускаются в JSON. Если вам нужно включить функцию, напишите ее в виде строки.

var text = '{ "name":"John", "age":"function () {return 30;}", "city":"New York"}';
var obj = JSON.parse(text);
obj.age = eval("(" + obj.age + ")");

0

Я знаю, что это более старый вопрос, однако никто не замечает этого решения, используя new Function()анонимную функцию, которая возвращает данные.


Просто пример:

 var oData = 'test1:"This is my object",test2:"This is my object"';

 if( typeof oData !== 'object' )
  try {
   oData = (new Function('return {'+oData+'};'))();
  }
  catch(e) { oData=false; }

 if( typeof oData !== 'object' )
  { alert( 'Error in code' ); }
 else {
        alert( oData.test1 );
        alert( oData.test2 );
      }

Это немного более безопасно, потому что он выполняется внутри функции и не компилируется в вашем коде напрямую. Поэтому, если внутри него есть объявление функции, оно не будет привязано к объекту окна по умолчанию.

Я использую это для простой и быстрой «компиляции» настроек конфигурации элементов DOM (например, атрибута данных).


0

Резюме:

Javascript (как браузер, так и NodeJS) имеют встроенный JSONобъект. На этом объекте есть 2 удобных способа борьбы с JSON. Они следующие:

  1. JSON.parse() принимает JSON качестве аргумента, возвращает объект JS
  2. JSON.stringify() Принимает объект JS в качестве аргумента, возвращает JSONобъект

Другие приложения:

К тому же для очень удобного обращения с JSONними можно использовать другие средства. Сочетание обоих JSONметодов позволяет очень легко сделать глубокие клоны массивов или объектов. Например:

let arr1 = [1, 2, [3 ,4]];
let newArr = arr1.slice();

arr1[2][0] = 'changed'; 
console.log(newArr); // not a deep clone

let arr2 = [1, 2, [3 ,4]];
let newArrDeepclone = JSON.parse(JSON.stringify(arr2));

arr2[2][0] = 'changed'; 
console.log(newArrDeepclone); // A deep clone, values unchanged


0

Вы также можете использовать reviverфункцию для фильтрации.

var data = JSON.parse(jsonString, function reviver(key, value) {
   //your code here to filter
});

Для получения дополнительной информации читайте JSON.parse.


0

JSON.parse - это правильный способ преобразования строки в объект, но если анализируемая строка не является объектом или строка неверна, она выдаст ошибку, которая приведет к разрыву остальной части кода, поэтому идеально подходит для переноса функции JSON.parse внутри try-catch

try{
   let obj = JSON.parse(string);
}catch(err){
   console.log(err);
}

-1

Попробуйте это. Это написано в машинописи.

         export function safeJsonParse(str: string) {
               try {
                 return JSON.parse(str);
                   } catch (e) {
                 return str;
                 }
           }

Я новичок в Typescript. Какую пользу это добавляет JSON.parse()?
Марк Л.

Если возникнет какое-либо исключение, будет возвращена сама входная строка
Supun Dharmarathne

-1
/**
 * Safely turning a JSON string into an object
 *
 * @param {String} str - JSON String
 * @returns deserialized object, false if error
 */
export function jsonParse(str) {
  let data = null;
  try {
    data = JSON.parse(str);
  } catch (err) {
    return false;
  }
  return data;
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.