如何将JSON字符串解码为UTF-8?

7

我已经使用json工作了一段时间了,问题在于我解码的字符串被编码为Latin-1,而我无法将其转换为UTF-8。因此,某些字符显示不正确(例如,'显示为')。

我在stackoverflow上读了几个问题,但它们似乎不起作用。

我正在处理的json结构如下所示(来自YouTube API):

...
"items": [
  {
   ...
   "snippet": {
    ...
    "title": "Powerbeats Pro “Totally Wireless” Except when you need a wire",
    ...
    }
   }
  ]

我使用以下方式对其进行编码:

response = await http.get(link, headers: {HttpHeaders.contentTypeHeader: "application/json; charset=utf-8"});
extractedData = json.decode(response.body);
dataTech = extractedData["items"];

然后我尝试将第二行修改为:


extractedData = json.decode(utf8.decode(response.body));

但是这会给我一个关于格式错误的错误。所以我将其更改为:
extractedData = json.decode(utf8.decode(response.bodyBytes));

这样做不会触发错误,但也没有解决问题。调整标头也无济于事。

我希望数据像现在一样存储在dataTech中,但以UTF-8编码进行编码。我做错了什么?

3个回答

16
首先,UTF-8通常是一种外部格式,由字节数组表示。它是作为HTTP响应的一部分通过网络发送的内容。在内部,Dart将字符串存储为UTF-16码点。utf8编码器/解码器在内部格式字符串和外部格式字节数组之间进行转换。
这就是为什么要使用utf8.decode(response.bodyBytes);获取原始的body字节并将其转换为内部字符串。(response.body基本上也是这样做的,但它根据响应头字符集选择字节->字符串解码器。当该字符集标头丢失时(通常是这样),http包选择Latin-1,如果你知道响应是以不同的字符集发送的,则明显无法正常工作。)通过自己使用utf8.decode,您可以覆盖http正在进行的(可能错误的)选择,因为您知道此特定服务器始终发送UTF-8。(当然可能不是!)
另一个提示:在请求中设置内容类型头很少有用。您通常不会发送任何内容,因此它没有类型!并且这不会影响服务器将发送回给您的内容类型或内容类型字符集。accept头可能是您要寻找的内容。这是向服务器提供的一条提示,告诉它您想要的内容类型 - 但并不是所有服务器都尊重它。所以为什么你的特殊字符仍然不正确?尝试在解码之前打印utf8.decode(response.bodyBytes),控制台中的显示是否正确?(为此类型的问题创建一个简单的Dart命令行应用程序非常有用;我发现在简单的十行Dart应用程序中设置断点和检查变量更容易。)尝试使用类似Wireshark的工具来捕获数据流中的字节(同样,拥有简单的Dart应用程序对此非常有用)。或者尝试使用Postman发送相同的请求并检查响应。

你是如何尝试展示这些字符的?可能只是你所使用的字体没有它们。


非常感谢您对我的问题进行了详细的回答。由于我是一名初级开发人员,我并没有真正理解头文件的概念,所以这非常有帮助。我检查了控制台输出,结果发现问题是json文件中的字符编码不正确。我只需使用replaceAll()替换它们即可。虽然这似乎不是一个理想的解决方案,但它确实起作用。 - Karol Wasowski

7

只需添加头部信息:'Accept': 'application/json; charset=UTF-8';对我很有效。


1

我的标题看起来像:

final response = await http.get(url, headers: {
    'Content-Type': 'application/json; charset=UTF-8',
    'Accept': 'application/json',
    'Authorization': 'Bearer $token',
  });

响应处理如下:

Map<String, dynamic> data = json.decode(utf8.decode(response.bodyBytes));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接