如何让.NET 6的System.Text.Json按UTF-8解析转义字符?
解决System.Text.Json解析Facebook备份JSON时的UTF-8转义字符乱码问题
Facebook备份的JSON文件中,特殊字符被转换成了UTF-8字节的十六进制转义序列(比如é的UTF-8字节0xC3 0xA1被写成\u00c3\u00a1),但System.Text.Json默认会将\uXXXX转义解析为UTF-16代码单元,导致出现Tamás这类乱码。要解决这个问题,需要自定义一个JsonConverter<string>来手动处理这种非标准的转义格式。
自定义转换器实现
这个转换器会遍历字符串,将\uXXXX格式的转义序列还原为UTF-8字节,最后统一用UTF-8解码得到正确字符串:
using System; using System.Collections.Generic; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; public class Utf8EscapedStringConverter : JsonConverter<string> { public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var rawString = reader.GetString(); if (rawString is null) return null; var utf8Bytes = new List<byte>(); int index = 0; while (index < rawString.Length) { // 识别\uXXXX格式的转义序列 if (rawString[index] == '\\' && index + 1 < rawString.Length && rawString[index + 1] == 'u') { // 提取四位十六进制字符并转换为字节 if (index + 5 <= rawString.Length && byte.TryParse(rawString.Substring(index + 2, 2), System.Globalization.NumberStyles.HexNumber, null, out var utf8Byte)) { utf8Bytes.Add(utf8Byte); index += 6; // 跳过整个\uXXXX序列(\u + 4位十六进制,共6个字符) continue; } } // 普通字符直接转换为UTF-8字节 utf8Bytes.AddRange(Encoding.UTF8.GetBytes(rawString[index].ToString())); index++; } return Encoding.UTF8.GetString(utf8Bytes.ToArray()); } public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) { // 序列化时沿用默认逻辑,若需要匹配Facebook格式可自行扩展 writer.WriteStringValue(value); } }
使用方式
有两种方式应用这个转换器:
1. 针对单个属性添加
在需要处理的字符串属性上标记[JsonConverter]特性:
class Msg { [JsonPropertyName("sender_name")] [JsonConverter(typeof(Utf8EscapedStringConverter))] public string SenderName { get; set; } }
2. 全局注册转换器
如果所有字符串属性都需要处理,可在JsonSerializerOptions中全局添加:
public class Program { public static void Main() { var data = @"{ ""sender_name"": ""Tam\u00c3\u00a1s"" }"; var options = new JsonSerializerOptions(); options.Converters.Add(new Utf8EscapedStringConverter()); var msg = JsonSerializer.Deserialize<Msg>(data, options); Console.WriteLine(msg.SenderName); // 输出:Tamás } }
原理说明
- Facebook的转义方式不符合JSON标准:JSON规范中
\uXXXX表示UTF-16代码单元,而Facebook是将UTF-8字节逐个转义。 - 自定义转换器通过解析
\uXXXX序列得到原始UTF-8字节,再用UTF-8解码,从而还原出正确的特殊字符。
内容的提问来源于stack exchange,提问作者quywsx
相关产品推荐
相关产品推荐

