Gson序列化HashMap时禁用HTML转义仍转义双引号的问题
问题分析与解决方案
首先明确:disableHtmlEscaping() 仅负责禁用HTML特殊字符(如<、>、&)的转义,不影响JSON字符串内部双引号的转义——这是因为JSON语法规定,字符串中的双引号必须被转义,属于Gson遵循规范的默认行为。
你遇到的核心问题是:将一段JSON格式的字符串当作普通字符串存入HashMap,Gson会按照普通字符串规则对其转义;但你期望这段内容被当作原生JSON结构输出,而非字符串。
正确解法
解法1:将JSON字符串解析为JSON对象/数组存入Map
把原本存为字符串的JSON内容,先解析成Gson的JsonElement(如JsonArray),再存入Map。Gson序列化时会直接输出原生JSON结构,不会转义双引号。
示例代码:
// 原始JSON字符串 String rawJsonStr = "[{\"key1\":\"value1\",\"key2\":\"value2\"}]"; // 解析为JsonArray Gson gsonParser = new Gson(); JsonArray jsonArray = gsonParser.fromJson(rawJsonStr, JsonArray.class); // 存入Map Map<String, Object> map = new HashMap<>(); map.put("test1", jsonArray); // 序列化 Gson gsonSerializer = new GsonBuilder().setPrettyPrinting().create(); String result = gsonSerializer.toJson(map);
输出结果(符合你期望的格式):
{ "test1": [ { "key1": "value1", "key2": "value2" } ] }
解法2:自定义TypeAdapter实现原始JSON输出(针对必须存字符串的场景)
如果必须在Map中存储字符串类型的JSON内容,可以自定义TypeAdapter,让Gson序列化时直接输出原始JSON内容,跳过字符串转义逻辑。
示例代码:
// 自定义TypeAdapter处理原始JSON字符串 class RawJsonStringAdapter extends TypeAdapter<String> { @Override public void write(JsonWriter out, String value) throws IOException { // 直接写入原始JSON内容,不做字符串转义 out.jsonValue(value); } @Override public String read(JsonReader in) throws IOException { // 反序列化逻辑按需实现 return in.nextString(); } } // 使用适配器序列化 Map<String, String> map = new HashMap<>(); map.put("test1", "[{\"key1\":\"value1\",\"key2\":\"value2\"}]"); Gson gson = new GsonBuilder() .setPrettyPrinting() .registerTypeAdapter(String.class, new RawJsonStringAdapter()) .create(); String result = gson.toJson(map);
注意:此适配器会影响所有字符串的序列化。若仅需针对特定字段,可在实体类字段上添加@JsonAdapter(RawJsonStringAdapter.class)注解;Map场景下可修改适配器逻辑,仅处理特定键对应的字符串。
为什么之前的方法无效
- 手动转义字符串:Gson序列化时会对字符串中的特殊字符再次转义,导致出现三重转义(
\\\\\") - setPrettyPrinting:仅用于格式化输出缩进,不改变转义逻辑
- 转JsonTree后获取字符串:JsonTree中的字符串已经是转义后的状态,
getAsString()和toString()只会返回转义后的内容
内容的提问来源于stack exchange,提问作者Jayden Chiu
相关产品推荐
相关产品推荐

