
restassured 默认 json 反序列化机制(如 jackson)与嵌套不规则结构(如 `"content": [{ "subject": "..."}, { "content": "..."}]`)存在兼容性问题,导致字段全为 null;改用 gson 手动解析并配置字段映射可彻底解决。
在使用 RestAssured 进行 API 测试时,若通过 response.extract().as(OriginalDTO.class) 直接将响应体反序列化为自定义 POJO,却出现所有字段均为 null 的现象,根本原因通常不是 POJO 定义错误,而是 RestAssured 内置的反序列化器(默认为 Jackson)无法正确处理该 JSON 的特殊结构。
观察提供的 JSON 响应,其核心特征是:顶层字段(如 "Content"、"Generic"、"Participants")均以数组形式包裹多个键值对对象,且每个对象内部结构稀疏、键名不统一、甚至包含空对象 {} 或 HTML 编码内容。例如:
"Content": [
{ "Subject": "EmailWithDOCAttachmentJCBKMJJ Test Email..." },
{ "Content": "An email includes Docx file as an attachment" },
{ "Content Html": "" },
{ "Record Date": "2023-01-30 12:27:53.000" }
]这种“数组内含异构 Map”的模式,不符合标准 Java Bean 的扁平化属性映射逻辑。Jackson 默认期望 "Content" 字段对应一个 List
✅ 正确做法:绕过 RestAssured 的自动反序列化,改用 Gson 手动解析,并合理建模数据结构
立即学习“Java免费学习笔记(深入)”;
-
使用 Gson 显式解析(推荐)
如答案所示,替换原代码:// ❌ 不可靠(依赖 RestAssured + Jackson,默认不支持嵌套动态键) OriginalDTO original = response.then().statusCode(200).extract().as(OriginalDTO.class);
为:
// ✅ 可靠(Gson 更灵活,支持 @SerializedName 映射复杂键名) Gson gson = new GsonBuilder() .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) // 可选:辅助处理下划线命名 .create(); OriginalDTO original = gson.fromJson(response.body().asString(), OriginalDTO.class); -
POJO 建模建议优化
当前 OriginalDTO 中 @SerializedName("Content") private Listcontent; 的设计隐含了“每个 Content 对象应同时拥有 Subject、Content、Content Html 等字段”,但实际 JSON 是「按语义拆分到不同对象」。更贴合实际的建模方式是: - 将 Content、Generic、Information 等字段声明为 List
- 或定义专用容器类(如 ContentEntry),配合 @SerializedName 精确映射每个可能的键:
public static class ContentEntry { @SerializedName("Subject") private String subject; @SerializedName("Content") private String content; @SerializedName("Content Html") private String contentHtml; @SerializedName("Record Date") private String recordDate; // getter/setter... }并在 OriginalDTO 中改为:
@SerializedName("Content") private Listcontent; -
关键注意事项
- ✅ 确保 @SerializedName 注解来自 com.google.gson.annotations.SerializedName(非 Jackson 的 @JsonProperty);
- ✅ 若使用 Lombok 的 @Getter/@Setter,需确认无构造函数冲突(Gson 要求默认构造函数或 @NoArgsConstructor);
- ⚠️ 避免在 POJO 中混用 Jackson(@JsonProperty)和 Gson(@SerializedName)注解,否则行为不可控;
- ? 调试技巧:先打印 response.body().asString() 确认响应内容完整,再用 gson.toJson(...) 验证序列化方向是否正常。
总结:RestAssured 的 as(Class) 方法本质是快捷封装,底层仍受限于所配 JSON 库的能力。面对非标准、高嵌套、键名不规范的 JSON(常见于遗留系统或松散定义的搜索/归档接口),主动接管反序列化流程,选用 Gson 并精准建模,是最稳定、最可控的实践方案。










