JSON 문자 인코딩-브라우저에서 UTF-8을 잘 지원합니까 아니면 숫자 이스케이프 시퀀스를 사용해야합니까?


91

리소스를 표현하기 위해 json을 사용하는 웹 서비스를 작성 중이며 json을 인코딩하는 가장 좋은 방법에 대해 약간 고민하고 있습니다. json rfc ( http://www.ietf.org/rfc/rfc4627.txt )를 읽으면 선호하는 인코딩이 utf-8이라는 것이 분명합니다. 그러나 rfc는 문자를 지정하기위한 문자열 이스케이프 메커니즘도 설명합니다. 나는 이것이 일반적으로 비 ASCII 문자를 이스케이프하는 데 사용되어 결과 utf-8 유효한 ASCII를 만든다고 가정합니다.

ASCII가 아닌 유니 코드 문자 (코드 포인트)가 포함 된 json 문자열이 있다고 가정 해 보겠습니다. 내 웹 서비스가 utf-8 인코딩하고 그것을 반환해야합니까, 아니면 모든 비 ASCII 문자를 이스케이프하고 순수한 ASCII를 반환해야합니까?

브라우저가 jsonp 또는 eval을 사용하여 결과를 실행할 수 있기를 바랍니다. 그것이 결정에 영향을 미칩니 까? utf-8에 대한 다양한 브라우저의 javascript 지원에 대한 지식이 부족합니다.

편집 : 결과를 인코딩하는 방법에 대한 주요 관심사는 브라우저에서 결과를 처리하는 것임을 분명히하고 싶었습니다. 내가 읽은 내용은 브라우저가 특히 JSONP를 사용할 때 인코딩에 민감 할 수 있음을 나타냅니다. 주제에 대해 정말 좋은 정보를 찾지 못했기 때문에 어떤 일이 발생하는지 테스트를 시작해야합니다. 이상적으로는 필요한 몇 개의 문자 만 이스케이프하고 결과를 utf-8로 인코딩하고 싶습니다.

답변:


89

JSON 사양 에는 디코더의 UTF-8 지원이 필요합니다 . 결과적으로 모든 JSON 디코더는 숫자 이스케이프 시퀀스를 처리 할 수있을뿐만 아니라 UTF-8을 처리 할 수 ​​있습니다. 자바 스크립트 인터프리터의 경우도 마찬가지입니다. 즉, JSONP가 UTF-8로 인코딩 된 JSON도 처리합니다.

JSON 인코더가 숫자 이스케이프 시퀀스를 대신 사용하는 기능은 더 많은 선택권을 제공합니다. 숫자 이스케이프 시퀀스를 선택할 수있는 한 가지 이유는 인코더와 의도 한 디코더 사이 의 전송 메커니즘 이 바이너리 안전하지 않은 경우입니다.

당신이 숫자 이스케이프 시퀀스를 사용할 수있는 또 다른 이유는 같은 스트림에 나타나는 특정 문자를 방지하는 것입니다 <, &그리고 "json으로 코드를 HTML 또는 잘못 그것을 해석 브라우저 HTML로 탈출하지 않고 배치되어있는 경우 HTML 시퀀스로 해석 될 수있는, . 이는 HTML 삽입 또는 교차 사이트 스크립팅에 대한 방어가 될 수 있습니다 (참고 : "및을 포함한 일부 문자는 JSON에서 이스케이프되어야 함 \).

PHP의 JSON 구현을 포함한 일부 프레임 워크 는 ASCII 외부의 모든 문자에 대해 인코더 측 에서 항상 숫자 이스케이프 시퀀스를 수행합니다. 이것은 제한된 전송 메커니즘 등과의 최대 호환성을위한 것입니다. 그러나 이것은 JSON 디코더에 UTF-8에 문제가 있다는 표시로 해석되어서는 안됩니다.

따라서 다음과 같이 사용할 것을 결정할 수 있다고 생각합니다.

  • 인코더와 디코더 간의 저장 또는 전송 방법이 바이너리 안전이 아닌 경우에만 UTF-8을 사용하십시오.

  • 그렇지 않으면 숫자 이스케이프 시퀀스를 사용하십시오.


1
"모든 JSON 디코더는 UTF-8을 처리 할 수 ​​있습니다."이것은 브라우저에 해당되지만 표준에 따라 모든 소프트웨어 디코딩 JSON이 UTF-8을 지원한다는 의미는 아닙니다.
Michael Mior

7
"모든 JSON 디코더는 UTF-8을 처리 할 수 ​​있습니다."는 말 그대로 사실입니다. UTF-8을 받아 들일 수없는 것이 있으면 JSON 디코더가 아닙니다. JSON 디코더와 비슷할 수 있지만 확실히 아닙니다.
thomasrutter

나는 당신이 사용하고있는 JSON 디코더의 정의에 달려 있다고 생각하지만, 공정한 요점 :)
Michael Mior

RFC 8259가 UTF-8 지원을 필수로 지정하는 이유는 세계가 표준화 한 것입니다. 이전의 구식 사양은 문자열을 유니 코드로 정의했지만 어떤 인코딩을 지정하지 않았습니다. 어쨌든 UTF-8에 표준화 된 구현과 업데이트 된 사양은이를 반영합니다.
thomasrutter 19

UTF-8 지원은 내가 말할 수있는 한 특정 소프트웨어에 대한 RFC에서 필수로 지정되지 않았습니다. UTF-8에 대한 유일한 언급은 폐쇄 시스템 외부에서 교환되는 JSON의 인코딩으로 사용되어야한다는 것입니다. 이는 모든 JSON 디코더 (RFC에서 사용되지 않는 언어)가 UTF-8을 지원해야 함을 의미하지는 않습니다.
Michael Mior 19-06-05

17

거기에 문제가있었습니다. "é"와 같은 문자로 문자열을 JSON으로 인코딩하면 "\ u00e9"를 반환하는 IE를 제외하고 모든 브라우저는 동일한 "é"를 반환합니다.

그런 다음 PHP json_decode ()에서 "é"를 찾으면 실패하므로 Firefox, Opera, Safari 및 Chrome의 경우 json_decode () 전에 utf8_encode ()를 호출해야합니다.

참고 : 내 테스트에서 IE와 Firefox는 기본 JSON 개체를 사용하고 다른 브라우저는 json2.js를 사용합니다.


10
아마 당신은 의미 utf8_encode(), php.net/manual/en/function.utf8-encode.php
베냐민

4
IE가 디코딩에 실패하면 사용중인 JSON 디코더의 버그입니다. 모든 JSON 디코더는 인코딩 된 형식을 성공적으로 디코딩해야합니다. 그렇지 않으면 JSON 디코더가 아닙니다. é 이스케이프 처리되지 않은 json_decode () 문제에 관해서는 공급하는 텍스트가 UTF-8이 아닐 수 있습니다. JSON 디코더는 PHP가 다른 많은 함수에서 일반적으로 UTF-8을 가정하지 않더라도 항상 UTF-8을 가정합니다. 이스케이프되지 않은 é를 포함 할 수 있고 화면에서 동일하게 보이지만 UTF-8이 아닌 다른 문자 인코딩이 있습니다. \ uXXXX 형식으로 인코딩하면이 문제를 해결할 수 있습니다.
thomasrutter 2013 년

간단히 말해서 JSON은 합법적으로 모든 유니 코드 인코딩 (UTF-8, UTF-16 BE / LE, UTF32 BE / LE, 바이트 순서 마커 포함 또는 제외)으로 올 수 있습니다. 그리고 ASCII는 UTF-8의 하위 집합이므로 ASCII로 올 수도 있습니다. 예를 들어 파서가 UTF-32를 허용하는지 여부는 모르겠습니다.
gnasher729

1
맞습니다. 그리고 파서는 UTF-8 이외의 것을 지원하는 데 필요하지 않습니다. 사양에서 : "JSON 텍스트는 UTF-8, UTF-16 또는 UTF-32로 인코딩되어야합니다. 기본 인코딩은 UTF-8이며 UTF-8로 인코딩 된 JSON 텍스트는 상호 운용이 가능합니다. 최대 구현 수만큼 성공적으로 읽을 수 있습니다. 다른 인코딩 (예 : UTF-16 및 UTF-32)의 텍스트를 성공적으로 읽을 수없는 구현이 많이 있습니다. 구현시 JSON 텍스트 시작 부분에 바이트 순서 표시를 추가하면 안됩니다. "
thomasrutter

@thomasrutter 인용하신 사양은 오래되었습니다. 현재 사양은 말한다 : " JSON 텍스트는 UTF-8을 사용하여 인코딩되어야 폐쇄 생태계의 일부가 아닌 시스템간에 교환 JSON 텍스트를 전송할 때 JSON의 이전 사양은 UTF-8의 사용을 요구하지 않은 그러나, 대부분의.. JSON 기반 소프트웨어 구현 중 대부분은 상호 운용성을 달성하는 유일한 인코딩 인 경우 UTF-8 인코딩을 사용하도록 선택했습니다. JSON 텍스트. "
Remy Lebeau

12

ASCII는 더 이상 없습니다. UTF-8 인코딩을 사용한다는 것은 ASCII 인코딩을 사용하지 않는다는 것을 의미합니다. 이스케이프 메커니즘을 사용해야하는 것은 RFC가 말하는 것입니다.

이스케이프해야하는 문자를 제외한 모든 유니 코드 문자는 인용 부호 안에 넣을 수 있습니다 : 인용 부호, 역 상선 및 제어 문자 (U + 0000 ~ U + 001F)


1
제공 한 따옴표를 읽으면 모든 유니 코드 문자를 이스케이프 할 필요가없고 몇 개의 특수 문자 만 이스케이프 할 필요가 있음을 알 수 있습니다. 그러나 결과를 인코딩해야합니다 (가급적이면 utf-8 사용). 따라서 질문은 "UTF-8 인코딩 인 경우 일반 유니 코드 문자를 이스케이프하는 이유"입니다.
schickb

또한 ascii로 인코딩 된 문자열은 utf-8의 순수한 하위 집합입니다. ASCII가 아닌 모든 문자에 json의 이스케이프를 사용하면 결과는 ascii이므로 utf-8입니다. 다양한 json 라이브러리 (예 : python simplejson)에는 ascii 결과를 강제하는 모드가 있습니다. 나는 아마도 브라우저에서의 실행과 같은 이유가 있다고 생각합니다.
schickb

일반 유니 코드 문자를 이스케이프 처리 할 때 문자열과 같은 메타 문자 인 컨텍스트에 있습니다. (제가 인용 한 RFC 청크는 문자열에 관한 것입니다. 죄송합니다. 명확하지 않았습니다.) 항상 ASCII 출력을 수행 할 필요는 없습니다. 깨진 브라우저로 디버깅하는 데 더 적합하다고 생각합니다.
chaos

7

나는 같은 문제에 직면했다. 그것은 나를 위해 작동합니다. 이것을 확인하십시오.

json_encode($array,JSON_UNESCAPED_UNICODE);

위의 내용은 PHP입니다. 질문은 PHP에만 국한 되지 않으며 PHP를 사용 하지 않을 수도 있는 웹 서비스에 대해서만 이야기 합니다 (이전 독자들은 여전히 ​​기억할 수 있습니다…)
ntninja

1

json rfc ( http://www.ietf.org/rfc/rfc4627.txt )를 읽으면 선호하는 인코딩이 utf-8이라는 것이 분명합니다.

참고로 RFC 4627은 더 이상 공식 JSON 사양이 아닙니다. 2014 년에 RFC 7159에 의해 폐기되었으며 , 이후 2017 년에 현재 사양 인 RFC 8259에 의해 폐기되었습니다 .

RFC 8259는 다음과 같이 말합니다.

8.1. 문자 인코딩

폐쇄 생태계의 일부가 아닌 시스템간에 교환되는 JSON 텍스트는 UTF-8 [RFC3629]를 사용하여 인코딩해야합니다 .

이전 JSON 사양에서는 JSON 텍스트를 전송할 때 UTF-8을 사용할 필요가 없습니다. 그러나 대부분의 JSON 기반 소프트웨어 구현은 상호 운용성을 달성하는 유일한 인코딩 인만큼 UTF-8 인코딩을 사용하도록 선택했습니다.

구현은 네트워크로 전송되는 JSON 텍스트의 시작 부분에 바이트 순서 표시 (U + FEFF)를 추가해서는 안됩니다. 상호 운용성을 위해 JSON 텍스트를 구문 분석하는 구현은 바이트 순서 표시의 존재를 오류로 처리하지 않고 무시할 수 있습니다.


0

나는 é char와 비슷한 문제가 있었다. 나는 "당신이 공급하는 텍스트가 UTF-8이 아닐 가능성이있다"라는 코멘트가 아마도 여기에있는 마크에 가깝다고 생각한다. 나는 깨닫고 utf8로 변경할 때까지 내 인스턴스의 기본 데이터 정렬이 다른 것이라고 느꼈습니다. 작업대. 최종 결과는 php가 데이터를 json으로 인코딩하지 않고 false를 반환한다는 것입니다. 내 문제를 일으키는 서버로 사용하는 브라우저는 중요하지 않습니다.이 문자가 있으면 php는 데이터를 utf8로 구문 분석하지 않습니다. 데이터가 존재 한 후 스키마를 utf8로 변환하거나 PHP 버그로 인한 것인지 확실하지 않다고 말합니다. 이 경우 사용json_encode(utf8_encode($string));

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.