“콘텐츠 유형 : application / json; charset = utf-8”은 정말로 의미 하는가?


284

REST 서비스에 JSON 본문으로 POST 요청을 할 때 Content-type: application/json; charset=utf-8메시지 헤더에 포함시킵니다. 이 헤더가 없으면 서비스에서 오류가 발생합니다. 부분 Content-type: application/json없이도 성공적으로 사용할 수 있습니다 ;charset=utf-8.

정확히 무엇을 charset=utf-8합니까? 문자 인코딩을 지정하지만 서비스가 없으면 제대로 작동합니다. 이 인코딩은 메시지 본문에있을 수있는 문자를 제한합니까?



8
흥미롭게도 IANA의 application/json미디어 유형 등록에 따르면 실제로는 charset종종 제공되지만 지원되는 매개 변수는 전혀 없는 것으로 보입니다 .
Uux November

1
I know it specifies the character encoding but the service works fine without it."작업"이 항상 "존재하는 코드 / 구성이 모든 일을 처리하는 가장 정확한 방법"을 의미하는 것은 아닙니다. 다른 상황에서는 작동하지 않을 수있는 모든 규칙과 가정에 따라 다릅니다. 나는 개인적으로 항상 가능한 한 분명하게 노력합니다.
WesternGun

3
"charset"매개 변수를 보내는 것은 올바르지 않으며 의미가 없습니다. RFC 8259, 섹션 11, 마지막 문장을 참조하십시오.
Julian Reschke

답변:


283

헤더는 컨텐츠가 인코딩 된 내용을 나타냅니다. 컨텐츠 자체에서 컨텐츠의 유형을 추론 할 수있는 것은 아닙니다. 즉, 컨텐츠를보고 그와 관련된 내용을 반드시 알 필요는 없습니다. 그것이 HTTP 헤더의 목적이며 수신자에게 (어쩌면) 다루고있는 컨텐츠의 종류를 알려줍니다.

Content-type: application/json; charset=utf-8UTF-8 문자 인코딩으로 인코딩 된 컨텐츠를 JSON 형식으로 지정합니다. JSON의 기본 (전용?) 인코딩은 UTF-8이므로 인코딩 지정은 JSON에 대해 약간 중복됩니다. 따라서이 경우 수신 서버는 JSON을 다루고 있으며 인코딩이 기본적으로 UTF-8이라고 가정하므로 헤더와 함께 또는 헤더없이 작동하는 것으로 알고 있습니다.

이 인코딩은 메시지 본문에있을 수있는 문자를 제한합니까?

아니요. 헤더와 본문에 원하는 것을 보낼 수 있습니다. 그러나 둘이 일치하지 않으면 잘못된 결과가 나타날 수 있습니다. 헤더에 내용이 UTF-8로 인코딩되어 있지만 실제로 Latin1로 인코딩 된 내용을 보내도록 지정하면 수신자는 가비지 데이터를 생성하여 Latin1로 인코딩 된 데이터를 UTF-8로 해석하려고 시도 할 수 있습니다. 물론 Latin1로 인코딩 된 데이터를 전송하도록 지정하고 실제로 그렇게하고 있다면 Latin1로 인코딩 할 수있는 256 자로 제한됩니다.


4
물론 JSON에서는 같은 이스케이프 시퀀스를 사용하여 비 Latin1 문자를 나타낼 수 있습니다 \u20AC.
dan04

31
json의 표준에 따르면 실제로 내용 인코딩에 latin1을 사용할 수 없습니다. JSON 컨텐츠는 유니 코드로 인코딩되어야합니다 (UTF-8, UTF-16 또는 UTF-32 (big 또는 little endian)).
Daniel Luna

20
application / json에는 charset 매개 변수가 없습니다.
Julian Reschke

7
@DanielLuna가 맞습니다 .ucs application/json변환 형식 중 하나 여야합니다. JSON의 처음 4 바이트가 제한되어 있기 때문에 그것은, 16, 또는 32 (8)의 경우에도, 당신은 항상 말할 수 의 엔디안을.
Jason Coco

4
중복되는 경우 charset=utf-8보안상의 이유로 포함시킬 수 있습니다 . github.com/shieldfy/API-Security-Checklist/issues/25
manuc66

143

@deceze의 주장을 입증하기 위해 기본 JSON 인코딩은 UTF-8입니다 ...

에서 IETF RFC4627 :

JSON 텍스트는 유니 코드로 인코딩해야합니다. 기본 인코딩은 UTF-8입니다.

JSON 텍스트의 처음 두 문자는 항상 ASCII 문자 [RFC0020]이므로 옥텟 스트림이 UTF-8, UTF-16 (BE 또는 LE) 또는 UTF-32 (BE 또는 LE)인지 확인할 수 있습니다. 처음 네 옥텟의 널 패턴을 살펴봄으로써

      00 00 00 xx  UTF-32BE
      00 xx 00 xx  UTF-16BE
      xx 00 00 00  UTF-32LE
      xx 00 xx 00  UTF-16LE
      xx xx xx xx  UTF-8

12
JSON을 텍스트 형식이 아닌 이진 형식으로 생각하는 것이 항상 도움이됩니다.
Sulthan

2
RFC4627은 RFC7159에 의해 폐기되었으며, 이는 루트 값이 문자열 일 수 있음을 나타냅니다 (이전 스펙과 명시 적으로 대조 됨). 이제 이것이 어떻게 구현됩니까? 스펙은 이와 관련하여 모호하며 세 가지 인코딩은 허용되지만 어떻게 구별 해야하는지는 밝히지 않습니다.
Fabio Beltramini

4
@FabioBeltramini JSON의 문자열에는 리터럴 null 문자가 포함되지 않기 때문에 위의 내용을 계속 유지해야합니다 (JSON의 null은 숫자 이스케이프 시퀀스로 인코딩해야합니다 "\u0000").
thomasrutter

3
실제로 UTF-16xx의 두 번째 문자에는이 경우 NULL이 없을 수 있지만 다른 바이트에서 인코딩을 결정할 수 있습니다. xx 00 00 00여전히 UTF-32LE이고 xx 00 xx xx여전히 UTF-16LE 00 xx xx xx이며 여전히 UTF-16BE입니다.
thomasrutter

20

참고 IETF RFC4627가 로 대체되었습니다 IETF RFC7158 . [8.1] 섹션에서 @Drew가 인용 한 텍스트를 다음과 같이 철회합니다.

Implementations MUST NOT add a byte order mark to the beginning of a JSON text.

유효한 json이 여전히 두 개의 ASCII 문자로 시작하므로 가정은 여전히 ​​유효합니다.
Larsing

단일 숫자는 유효한 JSON 파일이므로 하나의 문자
Nayuki

0

@deceze에 동의하지만 질문의 "서비스에서 오류가 발생했습니다" 부분 을 개발하고 싶습니다 .

http 415 로 이러한 종류의 오류가 발생합니다.

HTTP 415 지원되지 않는 미디어 유형 오류

HTTP 415 지원되지 않는 매체 유형 클라이언트 오류 응답 코드는 페이로드 형식이 지원되지 않는 형식이므로 서버가 요청 승인을 거부 함을 나타냅니다.

형식 문제는 요청에 표시된 Content-Type 또는 Content-Encoding 또는 데이터를 직접 검사 한 결과 일 수 있습니다.

즉, https://stackoverflow.com/a/22643964/914284 와 같은 예입니다.

  • 올바른 컨텐츠 유형을 설정해야하며 컨텐츠 유형 추가 : application / json 및 Accept : application / json과 같이 올바른 컨텐츠 유형을 승인해야합니다. 그렇지 않으면 기본값을 가정합니다

0

다트 http의 구현은 "charset = utf-8"덕분에 바이트를 처리하므로 응답에서 바이트를 읽을 때 "latin-1"폴백 문자 세트를 피하기 위해 여러 구현이 지원합니다. 필자의 경우 응답 본문 문자열의 형식이 완전히 손실되므로 utf8로 수동으로 인코딩하는 바이트를 수행하거나 서버의 API 응답에 해당 헤더 "inner"매개 변수를 추가해야합니다.


0

HttpClient를 사용하고 content-type이있는 응답 헤더를 가져 오는 중 application/jsonHttpClient가 기본적으로 ISO-8859-1 이므로 유니 코드를 사용하는 외국어 또는 기호와 같은 문자를 잃어 버렸습니다 . 따라서 가능한 문제를 피하기 위해 @WesternGun에서 언급 한대로 명시 적으로 명시하십시오.

서버로 인해 요청 된 헤더 문자 세트 ( method.setRequestHeader("accept-charset", "UTF-8");)를 처리하지 않으므로 응답 데이터를 그리기 바이트로 검색하고 UTF-8을 사용하여 문자열로 변환해야했습니다. 따라서 명시 적이며 기본값을 가정하지 않는 것이 좋습니다.

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