Безпечне перетворення рядка JSON в об’єкт


1334

З огляду на рядок даних JSON, як я можу безпечно перетворити цей рядок у об’єкт JavaScript?

Очевидно, що я можу зробити це небезпечно чимось на кшталт:

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

але це залишає мене вразливим до рядка JSON, що містить інший код, який здається дуже небезпечним просто зрівнятися.


77
У більшості мов eval несе додатковий ризик. Евал залишає відкриті двері для експлуатації хакерами. ЗАРАЗ, пам’ятайте, що весь JavaScript працює на клієнті. ОЧАКУЙТЕ, що це буде змінено хакерами. Вони можуть ПРАВИЛЬНО що завгодно, лише використовуючи консоль. Ви повинні побудувати свій захист на стороні сервера.
Beachhouse

19
Гаразд, зараз 2014 рік, і ви ніколи не повинні використовувати evalдля розбору рядка JSON, оскільки ви піддавали б свій код "ін'єкції коду". Використовуйте JSON.parse(yourString)замість цього.
Даніель

Чи є дані JSON буквальними?
shanechiu

@shanechiu: якщо ви маєте на увазі скалярний тип даних, так, так. Це лише рядок із синтаксисом ключових значень.
0zkr PM

Відповіді:


1960

JSON.parse(jsonString) це суто підхід JavaScript, якщо ви можете гарантувати досить сучасний браузер.


74
Я майже впевнений, що це безпечно для Node.js
Stephen

76
@vsync ви розумієте, що це ТІЛЬКИ чистий відповідь Javascript ... якщо ви прочитаєте опис тегу javascript, ви побачите це ... " Якщо тег для рамки / бібліотеки також не включений, чистий відповідь JavaScript - це очікується. ".. Я даю це +1 за те, що є єдиною відповіддю на javascript ...
iConnor


12
Якщо ви робите NodeJS, немає ніякого способу я би завантажував jQuery просто для розбору jsonString в об’єкт JSON. Тож підтверджуйте відповідь Джонатана
Антоній

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

Я не впевнений у інших способах це зробити, але ось як це зробити у прототипі (підручник 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'
});

НІ. Проблема полягає в тому, що ви очікуєте об'єкта JSON і (function(){ postCookiesToHostileServer(); }());в контексті "Вузла" ви зможете отримати або навіть більш неприємні речі.
Яур

Добре 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 - зло", і вони зроблять усе, щоб цього уникнути, навіть переписавши всю eval-функціональність ..
dinenevala

Є консенсус, що цей трюк є безпечним методом перетворення рядка в об'єкт JSON? Я міг би використовувати це, оскільки не потрібен додатковий імпорт js.
Хто

1
БУДЬ-ЯКИЙ підхід із використанням evalабо Functionоднаковою мірою вразливий
Slai

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 та масивів. Тож це не безпечний спосіб зробити це.
Тахсін Туркоз

Ви вже охоплювали цей nullвипадок раніше, і масив - це Object. Якщо ви хочете перевірити його, ви можете використовувати instanceof. Більше того, якщо ви дасте цій функції Array, вона зловить і return defколи вона могла б повернути ідеально гарний масив.
Серж К.

Мій коментар стосувався здорового глузду під час лову предметів. Моя функція може мати кілька запобіжних засобів, але використання вводу typeof не є кращим способом виявлення об'єктів взагалі.
Тахсін Туркоз

IMO, здоровий глузд не використовує toString()метод для перевірки того, чи є змінна об'єктом чи ні. Дивіться AngularJS , jQuery , Підкреслення або навіть розробники
Серж К.


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

За допомогою оператора objdot ( .) ви можете отримати доступ до властивостей об'єкта 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об'єкт. На цьому Об'єкті є два зручні методи для поводження 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{
   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.