Jak uniknąć znaków specjalnych w budowaniu łańcucha JSON?


200

Oto mój ciąg

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

Tutaj wiadomość zawiera pojedynczy znak cudzysłowu, który jest taki sam jak cytat używany w JSON. To, co robię, to uzupełnienie ciągu z danych wejściowych użytkownika, takich jak wiadomość. Muszę więc uciec od tego rodzaju specjalnych scenariuszy, które łamią kod. Ale oprócz zastąpienia ciągów istnieje jakiś sposób, aby je uciec, ale nadal pozwala HTML przetwarzać je z powrotem do właściwej wiadomości?


45
JSON używa tylko podwójnych cudzysłowów, a nie pojedynczych cudzysłowów, patrz json.org
Niels Bom

4
RFC 4627 stwierdza, że ​​analizatory składni muszą być w stanie analizować zgodny JSON (akapit 4) i mogą obsługiwać dodatkowe rozszerzenia inne niż JSON. Jednak w pkt 5 wyraźnie zaznaczono, że wszyscy producenci (generatory) MUSZĄ produkować WYŁĄCZNIE w 100% JSON zgodny. Tworzenie JSON ze znakami ramek, które nie wymagają ucieczki, jest szczególnie złym pomysłem. Zastanów się nad zastąpieniem apostrofów cytatami. ietf.org/rfc/rfc4627.txt
Luv2code

3
@ Luv2code Podczas gdy punkty, które robisz, pozostają prawdziwe, pamiętaj, że cytujesz przestarzałą specyfikację. Czytając RFC, zawsze używaj wersji tools.ietf.org/html , a nie wersji tekstowej. Wersje HTML są łatwiejsze do odczytania i zawierają łącza do podrozdziałów, a co najważniejsze, na górze wersji HTML znajduje się lista wszystkich kolejnych RFC, które aktualizują lub przestarzały ten, który czytasz. Gdybyś poszedł na tools.ietf.org/html/rfc4627 , zobaczyłbyś, że RFC 4627 jest przestarzały i został zastąpiony przez RFC 7159 .
Mark Amery

3
Dla osób czytających to w przyszłości RFC 7159 został z kolei zdezaktualizowany przez tools.ietf.org/html/rfc8259
Joram van den Boezem

Odpowiedzi:


286

Ciąg JSON musi być cytowany podwójnie, zgodnie ze specyfikacją , abyś nie musiał uciekać '.
Jeśli musisz użyć znaku specjalnego w ciągu JSON, możesz uciec przed nim, używając \znaku.

Zobacz listę znaków specjalnych używanych w JSON:

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


Jednak nawet jeśli jest to całkowicie niezgodne ze specyfikacją, autor może skorzystać \'.

Jest to złe, ponieważ:

  • Jest to niezgodne ze specyfikacją
  • To nie jest już poprawny ciąg JSON

Ale działa, jak chcesz lub nie.

W przypadku nowych czytelników zawsze używaj podwójnych cudzysłowów dla swoich ciągów Json.


30
„pojedyncze cytowane ciągi Json” ? To nonsens; ciągi w JSON mogą być zawsze cytowane podwójnie. Spróbuj JSON.parse("'foo'")na przykład w konsoli przeglądarki i obserwuj SyntaxError: Unexpected token '. Specyfikacja JSON jest naprawdę prosta i jasna . W JSON nie ma sekwencji ucieczki dla pojedynczych cudzysłowów, a ciąg JSON nie może być pojedynczym cudzysłowem.
Mark Amery

15
Nawet rzekomo wyjaśniająca aktualizacja tej odpowiedzi jest zła. Chociaż technicznie jest to prawdą, mylące jest stwierdzenie, że „nie trzeba” ucieczki ', podobnie jak technicznie to prawda, ale mylące jest stwierdzenie, że zgodnie z prawem nie trzeba mordować dzieci. Bardziej poprawne byłoby stwierdzenie, że nie można uciec '. \'jest niedozwoloną sekwencją ucieczki, a jeśli go użyjesz, wówczas twój JSON jest niepoprawny JSON i dowolny parser JSON się na nim zadławi. (Z pewnością JavaScript JSON.parsei Python json.loads.)
Mark Amery

2
Ta odpowiedź pozostaje kompletnym nonsensem po wielu edycjach. Twierdzisz, niesłusznie, że używanie ciągów cudzysłowów w JSON i stosowanie \'sekwencji ucieczki „działa, jak chcesz lub nie” . To nieprawda. Wzywam cię do pokazania dowolnego popularnego parsera JSON, który nie będzie się dusił na ciągach ani pojedynczych cudzysłowach \'. Wskazałem już, że JSON.parse("'foo'")i JSON.parse('"\\\'"') (w JavaScript) json.loads("'foo'")i json.loads('"\\\'"')(w Pythonie) oba zgłaszają wyjątki. Co, u licha, jest podstawą do twierdzenia, że ​​użycie tych konstrukcji „działa”?
Mark Amery

10
@ Luv2code ciekawy cytat. Lekko to interpretujesz; to nie znaczy, że każda postać może być uciekł po prostu poprzez umieszczenie backslash przed nim. Pełniejszy cytat brzmi: „Dowolny znak może być poprzedzony znakiem ucieczki. Jeśli znak znajduje się w podstawowej płaszczyźnie wielojęzycznej (od U ​​+ 0000 do U + FFFF), może on być reprezentowany jako sekwencja sześciu znaków . Alternatywnie istnieją dwa - sekwencje znaków unikają reprezentacji niektórych popularnych postaci. ”(moje podkreślenie). To znaczy , że możesz uciec 'jako \u0027, nie że możesz uciec jako \'.
Mark Amery

2
@ Nadal Luv2code, oznacza to, że mój pozytywny komentarz stwierdzający, że „nie możesz uciec '” (i porównujący taki czyn z morderstwem dzieci!) Jest technicznie błędny; dokładniejsze jest stwierdzenie, że można uciec, tylko nie tak \'. Nie zdawałem sobie sprawy, że wersja specyfikacji RFC odnosi się do sekwencji, takich \u0027jak „ucieczka” od reprezentowanych przez nich znaków. Kluczowy punkt, który \'jest nielegalny, jest jednak nadal prawdziwy i ważny.
Mark Amery

362

Jestem wstrząśnięty obecnością bardzo cenionych dezinformacji na tak szeroko oceniane pytanie dotyczące podstawowego tematu.

Ciągów JSON nie można cytować za pomocą pojedynczych cudzysłowów . Różne wersje specyfikacji ( oryginał Douglasa Crockforda, wersja ECMA i wersja IETF ) wszystkie stwierdzają, że ciągi muszą być cytowane z podwójnymi cudzysłowami. Nie jest to kwestia teoretyczna ani opinia, jak sugeruje obecnie przyjęta odpowiedź; jakikolwiek parser JSON w prawdziwym świecie będzie błędny, jeśli spróbujesz go przeanalizować jako ciąg cudzysłowu.

Wersja Crockforda i ECMA wyświetla nawet definicję łańcucha przy użyciu ładnego obrazu, co powinno jednoznacznie wyjaśnić:

Obraz przedstawiający definicję łańcucha ze specyfikacji JSON

Ładny obrazek zawiera również wszystkie prawidłowe sekwencje specjalne w ciągu JSON:

  • \"
  • \\
  • \/
  • \b
  • \f
  • \n
  • \r
  • \t
  • \u a następnie czterocyfrowe cyfry

Zauważ, że wbrew nonsensowi w niektórych innych odpowiedziach tutaj, \'nigdy nie jest prawidłową sekwencją ucieczki w ciągu JSON. Nie musi tak być, ponieważ ciągi JSON są zawsze podwójnie cytowane.

Wreszcie, zwykle nie powinieneś samodzielnie myśleć o ucieczce znaków podczas programowego generowania JSON (chociaż oczywiście będziesz to robił podczas ręcznej edycji, powiedzmy, pliku konfiguracyjnego opartego na JSON). Zamiast tego utwórz strukturę danych, którą chcesz zakodować, używając dowolnego rodzimego typu mapy, tablicy, łańcucha, liczby, wartości logicznych i zerowych, jakie posiada Twój język, a następnie zakoduj go do JSON za pomocą funkcji kodowania JSON. Taka funkcja jest prawdopodobnie wbudowana w dowolny używany język, na przykład JavaScript JSON.stringify, PHP json_encodelub Pythonjson.dumps. Jeśli używasz języka, który nie ma wbudowanej takiej funkcjonalności, prawdopodobnie możesz znaleźć bibliotekę parsowania i kodowania JSON do użycia. Jeśli po prostu użyjesz funkcji języka lub biblioteki do konwersji rzeczy do i z JSON, nigdy nie będziesz musiał znać reguł ucieczki JSON. To właśnie powinni zrobić tutaj nieuczciwie zadający pytanie.


4 bajty szesnastkowe lub skubane ?
leetbacoon

36

Wszyscy mówią o tym, jak uciec 'w 'cytowanym dosłownym łańcuchu literalnym. Jest tu o wiele większy problem: literały ciągów pojedynczych cudzysłowów nie są poprawnymi JSON . JSON jest oparty na JavaScript, ale to nie to samo. Jeśli piszesz literał obiektu w kodzie JavaScript, dobrze; jeśli faktycznie potrzebujesz JSON, musisz użyć ".

Dzięki ciągom podwójnie cytowanym nie musisz uciekać przed '. (A jeśli chciałbyś literału "w ciągu, użyłbyś \".)


1
Cześć, powiedziałeś z ciągami podwójnie cytowanymi, nie będziesz musiał uciekać przed '. Przykład wroga, jeśli moja wartość ciągu to "Member's_id" : 4, czy mówisz, że nie trzeba uciekać? Najwyraźniej mam problem z błędem kodowania: UTF-8 i jest on odczytywany jako Member�s. Jest to ręcznie wygenerowany plik json.
Shubham

1
'w łańcuchu znaków JSON nie można pominąć literału. Skopiowałeś go gdzieś? Może to naprawdę \u2019apostrof, a nie apostrof. Zgaduję: ktoś wpisał go w MS Word, co przekształciło go w cudzysłów, ponieważ uważa, że ​​wie najlepiej. Gramatycznie, dobry stary apostrof ASCII ( 'znany także jako \x27„pojedynczy cudzysłów”) jest tym, czego chcesz. Ale nadal dobrze byłoby naprawić problem z kodowaniem znaków, na wypadek, gdyby były inne podobne problemy. Wybierz kodowanie znaków i używaj go zarówno do odczytu, jak i zapisu. Lub uciec za pomocą \u.
David Knipe,

7

Większość tych odpowiedzi albo nie odpowiada na pytanie, albo jest niepotrzebnie długa w wyjaśnieniu.

OK, więc JSON używa tylko podwójnych cudzysłowów, rozumiemy to!

Próbowałem użyć JQuery AJAX, aby opublikować dane JSON na serwerze, a następnie zwrócić te same informacje. Najlepszym rozwiązaniem dla zamieszczonego przeze mnie pytania było użycie:

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

To pozwoli ci uciec od postaci.

Sugerował to także Mark Amery, Świetna odpowiedź BTW

Mam nadzieję, że to komuś pomoże.


0

Być może spóźniłem się na przyjęcie, ale to parsuje / unika pojedynczego cytatu (nie chcę wdawać się w bitwę podczas analizy składni vs ucieczki) ..

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

0

Odpowiedz na bezpośrednie pytanie:
Aby być bezpiecznym, zamień wymagany znak na \ u + 4-cyfrową wartość szesnastkową

Przykład: jeśli chcesz uciec od apostrofu, zamień na \ u0027
D'Amico staje się D \ u0027Amico

NICE REFERENCE: http://es5.github.io/x7.html#x7.8.4

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


-1 dla referencji. Pytanie dotyczy JSON, ale twoje odnośniki dotyczą JavaScript i wyświetlają sekwencje specjalne, które nie są poprawne w JavaScript \'.
Mark Amery

Dzięki Mark - naprawdę chciałem tylko podać alternatywny kąt - w zależności od tego, kto tu przyjedzie, może być to przydatne. Ale rozumiem o JSON i Javascript - dziękuję za bycie Ninja na forach.
Luigi D'Amico,

0

Użyj encodeURIComponent (), aby zakodować ciąg.

Na przykład. var lista_produktu = encodeURIComponent (JSON.stringify (lista_produktu));

Nie trzeba go dekodować, ponieważ serwer internetowy automatycznie robi to samo.


0

Używanie literałów szablonów ...

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

-2

Myślę, że wszyscy zgadzamy się, że pojedyncze cytaty jsons nie są prawdziwymi jsons. Tak czy inaczej, wciąż musimy rozwiązać kwestię ucieczki „w ciągu podwójnie cytowanego ciągu Json, przy braku bibliotek, które by to dla nas zrobiły.

Zamiana każdego „na \” NIE JEST WYSTARCZA: Użytkownik może wprowadzić dane wejściowe: \ i parsowanie ponownie się nie powiedzie (pomyśl dlaczego).

Zamiast tego najpierw zamień każdy \ na \ (podwójny ukośnik odwrotny). Tylko wtedy zamień każdy „na \” (ukośnik odwrotny i „).


-2

Aby umożliwić stosowanie pojedynczych cudzysłowów w ciągu podwójnie cytowanych ciągów dla celów json, należy podwoić pojedynczy cudzysłów. {„X”: „Jakie jest pytanie”} ==> {„X”: „Jakie jest pytanie”}

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

Sekwencja \ jest nieprawidłowa.


2
Podwojenie pojedynczego cudzysłowu w ciągu JSON nie umknie. Oznacza to po prostu, że Twój ciąg znaków zawiera dwa pojedyncze cudzysłowy zamiast jednego.
Mark Amery

-15

w odniesieniu do postu AlexB:

 \'  Apostrophe or single quote
 \"  Double quote

unikanie pojedynczych cudzysłowów jest poprawne tylko w ciągach
Json z pojedynczymi cytatami.

przykład:

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

14
Ciągi pojedynczego cudzysłowu nie są dozwolone w JSON. JSON nie jest javascript. JSON nie pozwala na uniknięcie pojedynczego cytatu. Zobacz json.org dla bardzo prostego dokumentu składni JSON.
srm

3
downvote - ponieważ pojedyncze cytaty jsons są nieprawidłowe!
DominikAngerer

Pojedyncze cytaty są niepoprawne w Json. Jeśli to możliwe, proszę pokazać działającą próbkę
Rohith
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.