Як уникнути особливих символів при побудові рядка JSON?


200

Ось моя рядок

{
    'user': {
        'name': 'abc',
        'fx': {
            'message': {
                'color': 'red'
            },
            'user': {
                'color': 'blue'
            }
        }
    },
    'timestamp': '2013-10-04T08: 10: 41+0100',
    'message': 'I'mABC..',
    'nanotime': '19993363098581330'
}    

Тут повідомлення містить єдиний лапок, який є тим самим, що і цитата, що використовується в JSON. Те, що я роблю, - це заповнити рядок із даних користувачів, таких як повідомлення. Отже, мені потрібно уникати таких спеціальних сценаріїв, які порушують код. Але хіба що замінити рядок, чи є якийсь спосіб змусити їх утекти, але все ж дозволяють HTML обробляти їх до правильного повідомлення?


45
JSON використовує лише подвійні лапки, а не одиничні цитати, див. Json.org
Niels Bom

4
RFC 4627 зазначає, що парсери повинні мати можливість аналізувати відповідні JSON (параграф 4) і можуть підтримувати додаткові розширення, що не є JSON. Однак у пункті 5 чітко зазначено, що всі виробники (генератори) ПОВИННІ виробляти ТОЛЬКО 100% сумісність JSON. Особливо поганою ідеєю є створення JSON з символами кадру, які не потребують втечі. Подумайте про заміну апострофів цитатами. ietf.org/rfc/rfc4627.txt
Luv2code

3
@ Luv2code Хоча точки, які ви створюєте, залишаються вірними, зауважте, що ви посилаєтесь на застарілу специфікацію. Читаючи RFC, завжди використовуйте версію tools.ietf.org/html , а не текстову версію. Версії HTML простіші для читання та посилання на підрозділи, а головне, вгорі версій HTML знаходиться список усіх наступних RFC, які оновлюють або застарівають той, який ви читаєте. Якби ви перейшли на tools.ietf.org/html/rfc4627, ви б побачили, що RFC 4627 є застарілим і його замінили RFC 7159 .
Марк Амері

3
Для людей, які читають це в майбутньому, RFC 7159, в свою чергу, застаріло на інструментах tools.ietf.org/html/rfc8259
van den Boezem

Повідомлення, пов’язані з цим - чи повинні бути ключі JSON оточені лапками?
RBT

Відповіді:


286

Рядок JSON повинен бути подвійним цитуванням відповідно до специфікацій , тому вам не потрібно бігти '.
Якщо вам потрібно використовувати спеціальний символ у рядку JSON, ви можете уникнути його, використовуючи \символ.

Дивіться цей список спеціальних символів, використовуваних у JSON:

\b  Backspace (ascii code 08)
\f  Form feed (ascii code 0C)
\n  New line
\r  Carriage return
\t  Tab
\"  Double quote
\\  Backslash character


Однак, навіть якщо це повністю суперечить специфікації, автор міг би використати \'.

Це погано, оскільки:

  • Це суперечить специфікаціям
  • Це вже не допустимий рядок JSON

Але воно працює, як хочеш ти чи ні.

Для нових читачів завжди використовуйте подвійні лапки для рядків json.


30
"рядки з цитованими єдиними json" ? Це нісенітниця; рядки в JSON можуть бути лише колись подвійними. Спробуйте, наприклад, JSON.parse("'foo'")у консолі браузера та спостерігайте за цим SyntaxError: Unexpected token '. Специфікація JSON дійсно проста і зрозуміла з цього приводу. У JSON немає жодної послідовності виходу для одиночних лапок, а рядок JSON не може бути одноцитованим.
Марк Амері

15
Навіть уточнене уточнення оновлення цієї відповіді погано. Хоча технічно це правда, оманливо сказати, що вам "не потрібно" бігти ', так само, як це технічно правда, але оманливо сказати, що юридично вам не потрібно вбивати дітей. Більш правильним було б сказати, що ти не можеш уникнути '. \'є незаконною послідовністю втечі, і якщо ви використовуєте її, ваш JSON не є дійсним JSON, і будь-який аналізатор JSON задушиться. (Безумовно, що це JavaScript JSON.parseта Python json.loads.)
Марк Амерді

2
Ця відповідь залишається безглуздим після багатьох редагувань. Ви помилково стверджуєте, що використання одноцитуваних рядків у JSON та використання \'послідовності втечі "працює, як ви цього хочете чи ні" . Це помилково. Я закликаю вас демонструвати в популярному використанні будь-який аналізатор JSON, який не задихатиметься на рядках, що котируються однозначно, або на \'послідовності. Я вже вказував, що JSON.parse("'foo'")і JSON.parse('"\\\'"') (у JavaScript), json.loads("'foo'")і json.loads('"\\\'"')(в Python) обидва викидають винятки. Що на землі є вашою основою для твердження, що використання цих конструкцій "працює"?
Марк Амері

10
@ Luv2code цікава цитата. Ви злегка трактуєте це; це не означає, що будь-якого персонажа можна уникнути, просто поставивши перед ним зворотний нахил. Більш повна цитата - "Будь-який символ може бути уникнути. Якщо персонаж знаходиться в базовій багатомовній площині (U + 0000 до U + FFFF), він може бути представлений у вигляді послідовності з шести символів . ... Як варіант, два -характеризація послідовності уникнення уявлень деяких популярних персонажів. "(наголос мій). Це говорить про те, що ти можеш втекти 'як \u0027, а не те, що можеш уникнути \'.
Марк Амерді

2
@ Luv2code все-таки це означає, що мій схвалений коментар, в якому йдеться про те, що "ти не можеш уникнути '" (і порівнюючи такий вчинок із вбивством дітей!) Технічно неправильно; точніше сказати, що ви можете уникнути цього, тільки не так \'. Я не розумів, що версія RFC специфікації згадує такі послідовності, як \u0027спосіб «втечі» від символів, які вони представляють. Однак, ключовий момент, який \'є незаконним, все ще є правдою та важливим.
Марк Амері

362

Мене приємно вражає наявність дещо інформованої дезінформації на такому високо розглянутому питанні про основну тему.

Рядки JSON не можна котирувати окремими цитатами . У різних версіях специфікації ( оригінал Дугласа Крокфорда, версія ECMA та версія IETF ) все зазначено, що рядки повинні бути котировані подвійними лапками. Це не теоретичне питання, ані питання думки, як це пропонує прийнята відповідь; будь-який синтаксичний аналізатор JSON у реальному світі помилиться, якщо ви спробуєте його проаналізувати одноцитованим рядком.

У версії Крокфорда та ECMA навіть відображається визначення рядка, використовуючи гарне зображення, яке повинно зробити точку однозначно зрозумілою:

Зображення, що показує визначення рядка зі специфікації JSON

Гарна картинка також перелічує всі законні послідовності втечі в рядку JSON:

  • \"
  • \\
  • \/
  • \b
  • \f
  • \n
  • \r
  • \t
  • \u далі чотиришарові цифри

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

Нарешті, вам не слід думати про те, щоб уникнути символів самостійно при програмному генеруванні JSON (хоча, звичайно, ви будете під час редагування вручну, скажімо, конфігураційного файлу на основі JSON). Натомість сформуйте структуру даних, яку ви хочете кодувати, використовуючи будь-які рідні типи карти, масиву, рядка, числа, булеві та нульові типи, а потім кодуйте її до JSON за допомогою функції кодування JSON. Така функція, ймовірно, вбудована в будь-яку мову, якою ви користуєтесь, як-от JavaScript JSON.stringify, PHP json_encodeчи Pythonjson.dumps. Якщо ви використовуєте мову, в якій не вбудована така функціональність, ви, ймовірно, можете знайти бібліотеку JSON для розбору та кодування для використання. Якщо ви просто використовуєте функції мови або бібліотеки для перетворення речей в JSON і з них, вам ніколи навіть не знатиметься правил втечі JSON. Ось що тут мав би зробити помилковий запитувач.


4 шістнадцяткових байта чи кусання ?
leetbacoon

36

Усі говорять про те, як вирватися 'з '-класованого рядка в прямому сенсі. Тут є набагато більша проблема: одноцитовані рядкові літерали не є дійсними JSON . JSON заснований на JavaScript, але це не те саме. Якщо ви пишете об'єкт буквально всередині коду JavaScript, добре; якщо вам дійсно потрібен JSON, вам потрібно скористатися ".

З подвійними цитатами рядків вам не потрібно буде уникати '. (А якщо б ви хотіли буквального "рядка в рядку, то використовуєте \".)


1
Привіт, ти сказав, що з двома цитатами, вам не потрібно буде уникати '. Приклад Foe, якщо в моєму рядку є значення "Member's_id" : 4, ти кажеш, що йому не потрібно бігти? Мабуть, у мене є проблема, коли вона дає помилку неправильного кодування: UTF-8, і вона читається як Member�s. Це файл, створений вручну json.
Shubham

1
'в рядковому рядку JSON не слід уникати. Ви скопіювали його звідкись? Можливо, це справді а \u2019, а не апостроф. Я здогадуюсь: хтось набрав його у MS Word, що перетворило його на лапки, бо вважає, що це найкраще знає. Граматично, старий добрий апостроф символу ASCII (він 'же \x27, який ми до цього часу ми називали "єдиною цитатою") - той, кого ви хочете. Але все-таки було б добре виправити проблему кодування символів, якщо є інші подібні проблеми. Тому виберіть кодування символів і використовуйте його як для читання, так і для запису. Або втекти, використовуючи \u.
Девід

7

Більшість із цих відповідей або не відповідає на питання, або надмірно довгі в поясненні.

Гаразд, JSON використовує лише подвійні лапки, ми отримуємо це!

Я намагався використовувати JQuery AJAX для розміщення даних JSON на сервері, а потім пізніше повернути ту саму інформацію. Найкращим рішенням розміщеного нами питання було використання:

var d = {
    name: 'whatever',
    address: 'whatever',
    DOB: '01/01/2001'
}
$.ajax({
    type: "POST",
    url: 'some/url',
    dataType: 'json',
    data: JSON.stringify(d),
    ...
}

Це дозволить уникнути символів для вас.

Це також запропонував Марк Амеррі, Велика відповідь BTW

Сподіваюся, що це комусь допоможе.


0

Можливо, я запізнився на партію, але це розбере / уникне єдиної цитати (не хочу вступати в бій на розбір проти втечі) ..

JSON.parse("\"'\"")

0

Відповідь на пряме запитання:
Щоб бути безпечним, замініть потрібний символ на \ u + чотиризначне значення

Приклад: Якщо ви хочете уникнути апострофа, 'замініть на \ u0027
D'Amico стає D \ u0027Amico

НІСЬКА СПРАВКА: http://es5.github.io/x7.html#x7.8.4

https://mathiasbynens.be/notes/javascript-escapes


-1 для довідок. Питання стосується JSON, але ваші пов’язані посилання стосуються JavaScript, і перелічіть послідовності виходу, які не дійсні в JavaScript \'.
Марк Амері

Дякую Марку - я дуже просто хотів дати альтернативний кут - залежно від того, хто сюди приїжджає, це може бути корисним. Але я сприймаю вашу думку про JSON & Javascript - Дякую, що ви ніндзя на форумах.
Луїджі Д'Аміко

0

Використовуйте encodeURIComponent () для кодування рядка.

Напр. var product_list = encodeURIComponent (JSON.stringify (product_list));

Не потрібно розшифровувати його, оскільки веб-сервер автоматично робить те саме.


0

Використання літеральних шаблонів ...

var json = `{"1440167924916":{"id":1440167924916,"type":"text","content":"It's a test!"}}`;

-2

Я думаю, що ми всі погоджуємось, що цитовані єдині циони не є справжніми дзвонами. Як би там не було, нам все-таки потрібно вирішити питання про втечу "в межах подвійного цитованого рядка json, за відсутності бібліотек для цього.

Заміна кожного "на \" НЕ ДУЖЕ: Користувач може ввести введення: \, а розбір, знову ж таки, не вдається (подумайте, чому).

Замість цього спочатку замініть кожну \ на \ (подвійний зворотний кут). Тільки тоді замініть кожне "на \" (зворотний косий рядок з наступним ").


-2

Щоб дозволити одинарні лапки в подвійному котируваному рядку з метою json, ви подвоюєте одиничну цитату. {"X": "У чому питання"} ==> {"X": "У чому питання"}

/codereview/69266/json-conversion-to-single-quotes

Послідовність \ "недійсна.


2
Подвоєння однієї цитати в рядку JSON не уникає цього. Це просто означає, що ваша рядок містить дві одиничні лапки замість однієї.
Марк Амері

-15

стосовно допису AlexB:

 \'  Apostrophe or single quote
 \"  Double quote

вимкнення одинарних лапок справедливо лише в рядах, що цитуються json
уникнення подвійних лапок є дійсним лише у подвійних цитатах json

приклад:

'Bart\'s car'       -> valid
'Bart says \"Hi\"'  -> invalid

14
Одно цитувані рядки не є законними в JSON. JSON - це не JavaScript. JSON не дозволяє уникати єдиної цитати. Дивіться на json.org дуже простий документ синтаксису JSON.
srm

3
downvote - адже одиночні цитати jsons не дійсні!
ДомінікАнгерер

Одиночні котирування є недійсними в json. Будь ласка, покажіть робочий зразок, якщо це можливо
Rohith
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.