【问题标题】:What does "Content-type: application/json; charset=utf-8" really mean?“内容类型:应用程序/json;charset=utf-8”的真正含义是什么?
【发布时间】:2012-03-04 12:32:32
【问题描述】:

当我向我的 REST 服务发出带有 JSON 正文的 POST 请求时,我在消息头中包含 Content-type: application/json; charset=utf-8。如果没有此标头,我会从服务中收到错误消息。我也可以在没有;charset=utf-8 部分的情况下成功使用Content-type: application/json

charset=utf-8 到底是做什么的?我知道它指定了字符编码,但没有它服务可以正常工作。这种编码是否限制了消息正文中可以包含的字符?

【问题讨论】:

  • 有趣的是,根据IANA's application/json Media Type Registration,似乎根本没有支持charset 参数,尽管在实践中经常提供。
  • I know it specifies the character encoding but the service works fine without it. "working" 并不总是意味着“现有的代码/配置是覆盖所有极端情况做一件事的最正确方法”。这取决于在其他情况下可能不起作用的所有约定和假设。就我个人而言,我总是尽可能地直言不讳。
  • 发送“charset”参数是不正确且没有意义的。请参阅 RFC 8259 第 11 节最后一句。

标签: character-encoding mime-types


【解决方案1】:

我完全同意@deceze,但我想开发这个“我从服务中收到错误”部分问题,

我们收到这种错误为 http 415

Http 415 不支持的媒体类型错误

HTTP 415 Unsupported Media Type 客户端错误响应代码表示服务器拒绝接受请求,因为负载格式是不受支持的格式。

格式问题可能是由于请求指定的Content-TypeContent-Encoding,或者是直接检查数据的结果。

换句话说,在this example 中可以看到。

  • 我们必须设置正确的内容类型并且我们必须接受正确的内容类型 如所见添加Content-Type: application/jsonAccept: application/json。否则,它将采用默认值

【讨论】:

    【解决方案2】:

    我正在使用 HttpClient 并返回内容类型为 application/json 的响应标头,由于 HttpClient 默认为 ISO-8859-1,因此我丢失了使用 unicode 的外语或符号等字符.因此,请尽可能明确,如@WesternGun 所述,以避免任何可能的问题。

    由于服务器没有为我处理请求的标头字符集 (method.setRequestHeader("accept-charset", "UTF-8");),因此无法处理,我必须将响应数据作为绘制字节检索并使用 UTF-8 将其转换为字符串。因此,建议明确并避免假设默认值。

    【讨论】:

      【解决方案3】:

      由于“charset=utf-8”,Dart http 的实现处理字节,所以我确信那里有几个实现支持这一点,以避免在从响应中读取字节时使用“latin-1”回退字符集。 就我而言,我完全失去了响应正文字符串的格式,因此我必须手动将字节编码为 utf8,或者在我的服务器的 API 响应中添加该标头“内部”参数。

      【讨论】:

        【解决方案4】:

        请注意,IETF RFC4627 已被 IETF RFC7158 取代。在第 [8.1] 节中,它撤回了@Drew 之前引用的文本:

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

        【讨论】:

        • 这个假设仍然成立,因为任何有效的 json 仍然以两个 ascii 字符开头。
        • 一个字符,因为单个数字是有效的 JSON 文件
        • RFC8259:实现不得在网络传输的 JSON 文本的开头添加字节顺序标记 (U+FEFF)。
        【解决方案5】:

        为了证实@deceze 声称默认 JSON 编码是 UTF-8...

        来自IETF RFC4627

        JSON 文本应以 Unicode 编码。默认编码是 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
        

        【讨论】:

        • 将 JSON 视为二进制格式而不是文本格式总是有帮助的。
        • 现在 RFC4627 已经被 RFC7159 淘汰了,RFC7159 指出根值可能是一个字符串(与之前的规范形成鲜明对比),现在如何实现?规范在这方面含糊不清,只是说允许使用三种编码,但没有说应该如何区分它们。
        • @FabioBeltramini 以上应该仍然成立,因为 JSON 中的字符串将不包含任何文字空字符(JSON 中的空值需要使用数字转义序列进行编码,即 "\u0000")。跨度>
        • 实际上UTF-16xx中的第二个字符在这种情况下可能没有NULL,但仍然可以从其他字节确定编码:xx 00 00 00仍然是UTF-32LE和@987654325 @ 仍然是 UTF-16LE,00 xx xx xx 仍然是 UTF-16BE。
        【解决方案6】:

        标头仅表示内容的编码内容。不一定可以从内容本身推断出内容的类型,即您不一定只看内容就知道如何处理它。这就是 HTTP 标头的用途,它们告诉接收者他们(假设)正在处理什么样的内容。

        Content-type: application/json; charset=utf-8 指定内容为 JSON 格式,以 UTF-8 字符编码进行编码。为 JSON 指定编码有点多余,因为 JSON 的默认(仅?)编码是 UTF-8。因此,在这种情况下,接收服务器显然很高兴知道它正在处理 JSON,并假定默认编码为 UTF-8,这就是它在有或没有标头的情况下工作的原因。

        此编码是否限制消息正文中可以包含的字符?

        没有。您可以在标题和正文中发送您想要的任何内容。但是,如果两者不匹配,您可能会得到错误的结果。如果您在标头中指定内容是 UTF-8 编码的,但您实际上发送的是 Latin1 编码的内容,则接收器可能会产生垃圾数据,试图将 Latin1 编码的数据解释为 UTF-8。当然,如果您指定要发送 Latin1 编码数据并且您实际上正在这样做,那么是的,您可以使用 Latin1 编码的 256 个字符。

        【讨论】:

        • 当然,在 JSON 中,您仍然可以使用转义序列来表示非拉丁字符,例如 \u20AC
        • 根据 json 的标准,实际上不允许使用 latin1 对内容进行编码。 JSON 内容必须编码为 un​​icode,无论是 UTF-8、UTF-16 还是 UTF-32(大端或小端)。
        • application/json上没有charset参数。
        • @DanielLuna 是对的,application/json 必须采用 ucs 转换格式之一。此外,由于 JSON 的前四个字节是有限的,您始终可以判断它是 8、16 还是 32 以及它的字节序。
        • 事件如果是多余的,出于安全原因,您可能希望包含charset=utf-8github.com/shieldfy/API-Security-Checklist/issues/25
        猜你喜欢
        • 2013-11-17
        • 2020-03-20
        • 2013-05-09
        • 1970-01-01
        • 2018-11-06
        • 2018-07-24
        • 1970-01-01
        • 1970-01-01
        • 2015-11-01
        相关资源
        最近更新 更多