「コンテンツタイプ:application / json; charset = utf-8」は本当に意味ですか?


284

JSONボディを含むPOSTリクエストをRESTサービスにContent-type: application/json; charset=utf-8送信するとき、メッセージヘッダーに含めます。このヘッダーがないと、サービスからエラーが発生します。部分がContent-type: application/jsonなくても問題なく使用でき;charset=utf-8ます。

正確には何をしcharset=utf-8ますか?文字エンコーディングを指定していることはわかっていますが、サービスがなくてもサービスは正常に動作します。このエンコードにより、メッセージ本文に含めることができる文字が制限されますか?



8
興味深いことに、IANAのapplication/jsonMedia Type Registrationによると、サポートcharsetされているパラメーターはまったくないようですが、実際には多くの場合提供されています。
Uux、2014年

1
I know it specifies the character encoding but the service works fine without it.「機能する」とは、必ずしも「既存のコード/構成が、1つのことを行うためのすべての主要なケースをカバーする最も正しい方法である」ことを意味するわけではありません。それは、他の状況では機能しない可能性のあるすべての規則と仮定に依存します。私個人としては、常にできるだけ明示的になるようにしています。
WesternGun

3
「charset」パラメータの送信は正しくなく、意味がありません。RFC 8259、セクション11、最後の文を参照してください。
ジュリアンレシュケ

回答:


283

ヘッダーは、コンテンツがエンコードされている内容を示すだけです。コンテンツ自体からコンテンツのタイプを推測することは必ずしも可能ではありません。つまり、コンテンツを見て、何をすべきかを知ることができるとは限りません。これがHTTPヘッダーの目的であり、(おそらく)処理しているコンテンツの種類を受信者に伝えます。

Content-type: application/json; charset=utf-8コンテンツをJSON形式に指定し、UTF-8文字エンコードでエンコードします。JSONのデフォルトの(のみ?)エンコーディングはUTF-8であるため、エンコーディングの指定はJSONにとって多少冗長です。したがって、この場合、受信サーバーはJSONを処理していて、デフォルトでエンコーディングがUTF-8であると想定していることを知って満足しているようです。そのため、ヘッダーの有無にかかわらず動作します。

このエンコードにより、メッセージ本文に含めることができる文字が制限されますか?

いいえ。ヘッダーと本文で何でも送信できます。ただし、2つが一致しない場合、誤った結果が得られる可能性があります。ヘッダーでコンテンツがUTF-8エンコードされていることを指定しているが、実際にLatin1エンコードされたコンテンツを送信している場合、受信者は不要なデータを生成し、Latin1エンコードされたデータをUTF-8として解釈しようとする可能性があります。もちろん、Latin1でエンコードされたデータを送信することを指定し、実際に送信する場合、そうです、Latin1でエンコードできる256文字に制限されます。


4
もちろん、JSONでは、のようなエスケープシーケンスを使用して非Latin1文字を表すこともできます\u20AC
dan04

31
jsonの標準によると、コンテンツのエンコードに実際にlatin1を使用することは許可されていません。JSONコンテンツは、UTF-8、UTF-16、またはUTF-32(ビッグエンディアンまたはリトルエンディアン)のように、ユニコードとしてエンコードする必要があります。
Daniel Luna

20
application / jsonにはcharsetパラメータはありません。
Julian Reschke 2013年

7
@DanielLunaは正しいapplication/jsonです。ucs変換フォーマットの1つでなければなりません。また、JSONの最初の4バイトは制限されているので、それが8、16、または32であるかどうか、およびそのエンディアンネスであるかを常に知ることができます。
Jason Coco

4
冗長性がある場合はcharset=utf-8、セキュリティ上の理由から含める必要があるイベント:github.com/shieldfy/API-Security-Checklist/issues/25
manuc66

143

デフォルトのJSONエンコーディングがUTF-8であるという@decezeの主張を実証するには...

IETF RFC4627から:

JSONテキストはUnicodeでエンコードする必要があります。デフォルトのエンコーディングはUTF-8です。

JSONテキストの最初の2文字は常にASCII文字であるため[RFC0020]、オクテットストリームがUTF-8、UTF-16(BEまたはLE)、またはUTF-32(BEまたはLE)のいずれであるかを判別できます。最初の4つのオクテットのヌルのパターンを確認します。

      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をテキスト形式ではなく、バイナリ形式として考えることは常に役立ちます。
スルタン

2
RFC4627はRFC7159によって廃止されたため、ルート値は(前の仕様とは明確に対照的に)文字列である可能性がありますが、これはどのように実装されますか?仕様はこの点に関して曖昧であり、3つのエンコーディングが許可されていると述べていますが、どのようにそれらを区別することになっているのかではありません。
Fabio Beltramini、2015年

4
@FabioBeltramini JSONの文字列にはリテラルのnull文字が含まれないため、上記は引き続き保持されます(JSONのnullは数値エスケープシーケンスでエンコードする必要があります"\u0000")。
thomasrutter、2015年

3
実際にはUTF-16xxの2番目の文字は、その場合にNULLを持たないかもしれないが、それでも他のバイトコードから決定することが可能であろう:xx 00 00 00まだUTF-32LEでありxx 00 xx xx、依然としてUTF-16LEで00 xx xx xx依然としてUTF-16BEです。
thomasrutter 2015年

20

ことに注意してくださいIETF RFC4627に取って代わられているIETF RFC7158。セクション[8.1]では、@ Drewが以前に引用したテキストを次のように撤回します。

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

ただし、有効なjsonは2つのASCII文字で始まるため、この仮定は依然として当てはまります。
17

単一の数字は有効なJSONファイルであるため、1文字
Nayuki

0

私は@decezeにまったく同意しますが、質問の「サービスからエラーが発生する」部分を開発したいと思います

この種のエラーはhttp 415として発生します

HTTP 415 Unsupported Media type error

ペイロードの形式がサポートされていない形式であるため、HTTP 415 Unsupported Media Typeクライアントエラー応答コードは、サーバーが要求の受け入れを拒否したことを示します。

フォーマットの問題は、リクエストに示されたContent-TypeまたはContent-Encodingが原因であるか、データを直接検査した結果である可能性があります。

つまり、https://stackoverflow.com/a/22643964/914284この例に見られるようなものです。

  • 正しいコンテンツタイプを設定する必要があり、Add Content-Type:application / jsonおよびAccept:application / jsonのように正しいコンテンツタイプを受け入れる必要があります。それ以外の場合は、デフォルトを想定します

0

Dart httpの実装は、その「charset = utf-8」のおかげでバイトを処理するので、応答からバイトを読み取るときに「latin-1」フォールバック文字セットを回避するために、いくつかの実装がこれをサポートしていると思います。私の場合、応答の本文の文字列の形式が完全に失われるため、手動でバイトエンコードを実行してutf8にするか、サーバーのAPI応答にそのヘッダーの「内部」パラメーターを追加する必要があります。


0

私はHttpClientを使用していて、content-typeがの応答ヘッダーを取得していたapplication/jsonため、HttpClientのデフォルトがISO-8859-1であるため、Unicodeを使用する外国語や記号などの文字が失われました。したがって、起こりうる問題を回避するために、@ WesternGunで言及されているように、できるだけ明示的にしてください。

サーバーのためにリクエストされたヘッダーの文字セット(method.setRequestHeader("accept-charset", "UTF-8");)を処理できないため、ハンドルデータを取得する方法はありません。応答データを描画バイトとして取得し、UTF-8を使用して文字列に変換する必要がありました。そのため、明示的で、デフォルト値の想定を避けることが推奨されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.