在Android开发中,Retrofit是常用的网络请求框架,当接口需要传输包含HTML标签的JSON数据时,默认的Gson转换器可能会自动转义HTML的特殊字符,导致接收端无法正确解析标签内容。本文将介绍几种优雅处理这类场景的方法。

问题分析
默认情况下,Gson会将JSON中的<、>等特殊字符转义为对应的Unicode编码或者转义序列,比如把<div>转成u003cdivu003e,如果后端没有做对应的反转义处理,就会出现内容显示异常的问题。
解决方案一:自定义Gson转换器
我们可以通过自定义Gson实例,关闭HTML字符的转义功能,让JSON中的HTML标签保持原始格式传输。
// 自定义Gson实例,禁用HTML转义
Gson gson = new GsonBuilder()
.disableHtmlEscaping() // 关键配置,关闭HTML转义
.create();
// 构建Retrofit实例时传入自定义Gson
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://ipipp.com/api/")
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
这种方式全局生效,所有通过该Retrofit实例发起的请求和接收的响应,都不会对HTML特殊字符进行转义,适合整个项目都需要传输HTML标签的场景。
解决方案二:使用@SerializedName配合自定义序列化器
如果只有部分字段需要传输HTML标签,不需要全局关闭转义,可以为对应字段自定义序列化规则。
// 自定义HtmlString适配器
public class HtmlStringAdapter extends TypeAdapter<String> {
@Override
public void write(JsonWriter out, String value) throws IOException {
if (value == null) {
out.nullValue();
} else {
// 直接写入原始字符串,不做转义
out.jsonValue(""" + value.replace(""", "\"") + """);
}
}
@Override
public String read(JsonReader in) throws IOException {
return in.nextString();
}
}
// 定义数据模型
public class Article {
@SerializedName("title")
private String title;
@SerializedName("content")
@JsonAdapter(HtmlStringAdapter.class) // 为该字段指定自定义适配器
private String content; // 这个字段可以包含HTML标签
// 省略getter和setter
}
解决方案三:传输前手动转义/反转义
如果无法修改Retrofit的配置,也可以在数据传入请求体之前,手动对HTML标签进行转义,接收后再反转义。
import android.text.TextUtils;
public class HtmlTransferUtil {
// 转义HTML特殊字符为实体编码
public static String escapeHtml(String content) {
if (TextUtils.isEmpty(content)) {
return content;
}
return content.replace("&", "&")
.replace("<", "<")
.replace(">", ">")
.replace(""", """)
.replace("'", "'");
}
// 反转义实体编码为HTML标签
public static String unescapeHtml(String content) {
if (TextUtils.isEmpty(content)) {
return content;
}
return content.replace("<", "<")
.replace(">", ">")
.replace(""", """)
.replace("'", "'")
.replace("&", "&");
}
}
// 使用示例
Article article = new Article();
article.setTitle("测试文章");
article.setContent(HtmlTransferUtil.escapeHtml("<div>这是带标签的内容</div>")); // 传输前转义
注意事项
- 关闭全局HTML转义后,如果JSON本身包含需要转义的字符,可能会出现格式错误,需要根据实际场景选择方案。
- 如果后端接口对接收的JSON格式有特殊要求,优先和后端约定好转义规则,避免两端处理不一致。
- 自定义TypeAdapter时,要注意处理null值和特殊字符,避免序列化/反序列化时出现异常。
方案对比
| 方案 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 自定义Gson关闭转义 | 全局需要传输HTML标签 | 配置简单,全局生效 | 可能影响其他不需要HTML标签的字段 |
| 自定义字段适配器 | 仅部分字段需要传输HTML标签 | 粒度细,不影响其他字段 | 需要为每个字段单独配置,代码量稍大 |
| 手动转义反转义 | 无法修改Retrofit配置的场景 | 不依赖框架配置,兼容性好 | 需要手动处理,容易遗漏转义步骤 |