转JSON时汉字显示异常?这些方法帮你解决
在开发过程中,将数据转换为JSON格式是常见操作,但经常会遇到汉字显示异常的问题——要么变成\u开头的Unicode编码(如\u4e2d\u56fd),要么出现乱码(如),要么直接显示为null,这些问题的根源通常与字符编码、序列化配置或数据格式有关,本文将详细分析汉字显示异常的原因,并提供针对性的解决方案。
为什么JSON中的汉字会显示异常?
要解决问题,先得明白原因,JSON本身是一种基于文本的数据格式,其规范中明确要求字符串必须使用UTF-8编码(或其子集ASCII),但实际开发中,汉字显示异常往往源于以下几个核心原因:
字符编码不一致:数据源与JSON解析的“语言”不同步
JSON字符串的编码和解码必须统一,如果数据源(如数据库、文本文件)使用的是GBK、GB2312等中文编码,而序列化时默认按UTF-8处理,或者解析时编码与生成时不匹配,就会导致汉字乱码或编码显示。
Java中用ISO-8859-1编码读取GBK的汉字,再转为JSON时,汉字会变成\u编码;Python中如果文件保存为GBK但JSON库默认按UTF-8解析,也会出现乱码。
序列化/反序列化时未正确处理编码
不同编程语言的JSON库在处理汉字时,默认行为可能不同,有些库会自动将汉字转为Unicode编码(如Java的Jackson默认开启WRITE_ENUMS_USING_INDEX时,可能将非ASCII字符转为\u),有些则需要手动指定编码参数。
JavaScript中直接使用JSON.stringify()处理汉字时,通常不会出现问题(因为JS内部统一使用UTF-16),但如果数据是从后端获取的,而后端未正确设置响应头,也可能显示异常。
数据源本身已损坏或编码错误
如果数据在存储或传输过程中被错误编码(如二进制数据被误转为文本),或者数据库字段编码与插入数据不匹配(如MySQL表的charset是latin1但插入了中文),即使后续JSON序列化正确,汉字也无法正常显示。
特殊字符未转义
JSON规范要求某些特殊字符(如、\、、换行符等)必须转义,但汉字本身无需转义,如果数据中包含未转义的特殊字符(如"中国"中的未转义),可能导致JSON解析失败,间接让汉字显示异常。
解决方案:让汉字在JSON中正确显示的实用技巧
统一字符编码:全程使用UTF-8
核心原则:从数据存储到序列化、传输、解析,全程使用UTF-8编码,避免编码不一致。
- 数据存储:数据库(如MySQL、PostgreSQL)的表字符集设置为
utf8mb4(支持Emoji和特殊字符),字段字符集也设为utf8mb4;文件存储时,保存为UTF-8编码(如Python中open('file.txt', 'w', encoding='utf-8'))。 - 序列化时指定编码:
- Java(Jackson):
ObjectMapper mapper = new ObjectMapper(); mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 确保序列化时使用UTF-8(默认已支持,但需确保响应头正确)。 - Python:
json.dumps(data, ensure_ascii=False)——ensure_ascii=False是关键,否则默认会将非ASCII字符转为\u编码。 - JavaScript:无需额外处理,
JSON.stringify()默认按UTF-16处理,但需确保后端响应头Content-Type: application/json; charset=utf-8。
- Java(Jackson):
- 传输层设置:HTTP响应头或请求头中明确指定字符集,如
Content-Type: application/json; charset=utf-8(Java中可通过response.setContentType("application/json;charset=utf-8")设置)。
根据场景调整序列化配置
(1)强制输出汉字而非Unicode编码
部分JSON库默认将非ASCII字符转为Unicode编码(如Java的Jackson、C#的Json.NET),需手动关闭此行为:
- Java(Jackson):
ObjectMapper mapper = new ObjectMapper(); mapper.configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, false); // 关闭非ASCII字符转义 String json = mapper.writeValueAsString(data); // 输出"中国"而非"\u4e2d\u56fd"
- Python:
import json data = {"country": "中国"} json_str = json.dumps(data, ensure_ascii=False) # 关键参数 print(json_str) # 输出:{"country": "中国"} - C#:
var json = JsonConvert.SerializeObject(data, Formatting.Indented, new JsonSerializerSettings { // 禁用Unicode转义 StringEscapeHandling = StringEscapeHandling.EscapeNonAscii });
(2)处理特殊字符转义
JSON规范要求特殊字符必须转义,如需写成\",\需写成\\,换行符需写成\n,如果数据包含这些字符,需让JSON库自动处理,而非手动转义(避免重复转义):
- Python示例:
data = {"text": "他说:"你好!""} json_str = json.dumps(data, ensure_ascii=False) # 自动转义双引号 print(json_str) # 输出:{"text": "他说:\"你好!\""}
检查数据源编码,修复已损坏数据
如果数据源编码错误,需先修复数据,再进行JSON序列化:
- 数据库数据修复:若MySQL表使用
latin1但存了中文,可通过ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4;转换字符集,或使用CONVERT()函数在查询时转码:SELECT CONVERT(column_name USING utf8) FROM table_name;。 - 文件数据修复:若文件编码为GBK但误按UTF-8读取,需先按原编码读取,再转存为UTF-8:
# 读取GBK文件并转为UTF-8 with open("gbk_file.txt", "r", encoding="gbk") as f: content = f.read() with open("utf8_file.txt", "w", encoding="utf-8") as f: f.write(content)
调试与验证:确保JSON格式正确
汉字显示异常有时是JSON格式错误导致的间接问题(如未闭合的引号、逗号),可通过以下方式验证:
- 在线JSON校验工具:如JSONLint,粘贴JSON字符串检查格式是否正确。
- 打印原始数据:序列化前打印原始数据,确认汉字是否正常(如
print(data)查看Python字典中的汉字)。 - 抓包工具检查:如果是HTTP接口响应,用Charles或Fiddler抓包,查看响应体的
Content-Type和原始字节流(确保字节流是UTF-8编码的汉字)。
常见场景示例与代码
场景1:Python中JSON汉字显示为\u编码
问题:json.dumps({"name": "张三"})输出{"name": "\u5f20\u4e09"}。
原因:json.dumps()默认开启ensure_ascii=True,将非ASCII字符转为Unicode编码。
解决:
import json
data = {"name": "张三"}
json_str = json.dumps(data, ensure_ascii=False) # 关闭ASCII转义
print(json_str) # 输出:{"name": "张三"}
场景2:Java中Jackson序列化汉字显示Unicode
问题:ObjectMapper默认将"中国"转为"\u4e2d\u56fd"。
原因:JsonGenerator.Feature.ESCAPE_NON_ASCII默认开启。
解决:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
public class JsonExample {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.ESCAPE_NON_ASCII, false); // 关键配置
String json = mapper.writeValueAsString(new Country("中国"));
System.out.println(json); // 输出:{"name":"中国"}
}
}
class Country {
private String name;
public Country(String name) { this.name = name; }
public String getName() { return name; }
}


还没有评论,来说两句吧...