如何在自定义 Jackson 序列化器中正确序列化嵌套对象的字段

发布时间 - 2026-01-22 00:00:00    点击率:

当使用自定义 jackson `stdserializer` 处理多态集合(如 `list`)时,若仅调用 `writenullfield()` 会导致子类字段丢失;应改用 `writeobjectfield()` 委托 jackson 默认序列化逻辑,才能完整输出子类的全部字段。

在 Jackson(尤其是 XmlMapper)中实现多态序列化时,一个常见误区是:在自定义序列化器中手动写入字段名但未真正序列化对象内容。例如原代码中使用:

jg.writeNullField(animal.getClass().getSimpleName());

该方法仅生成一个空标签(如 ),完全跳过了 Dog 实例自身的序列化流程,因此 breed 和 age 字段自然不会出现。

✅ 正确做法是利用 Jackson 提供的 委托序列化机制 —— 调用 JsonGenerator#writeObjectField(String fieldName, Object value)。此方法会自动触发 Jackson 对 value 的标准序列化逻辑(包括字段发现、注解处理、类型适配等),从而保留 Dog 类中所有可序列化的公共字段(或按 @JsonProperty 配置的字段)。

以下是修复后的 ZooSerializer 完整实现:

public class ZooSerializer extends StdSerializer {
    public ZooSerializer() {
        this(null);
    }

    public ZooSerializer(Class t) {
        super(t);
    }

    @Override
    public void serialize(Zoo zoo, JsonGenerator jg, SerializerProvider sp) throws IOException {
        jg.writeStartObject();
        for (Animal animal : zoo.animals) {
            String typeName = animal.getClass().getSimpleName();
            jg.writeObjectField(typeName, animal); // ✅ 关键:委托 Jackson 序列化 animal 实例
        }
        jg.writeEndObject();
    }
}

运行测试后,输出将变为符合预期的 XML 结构:


  
    Collie
    6
  

⚠️ 重要注意事项:

  • 此方案依赖 Jackson 的默认 POJO 序列化规则(如字段可见性、@JsonProperty、@JsonIgnore 等),请确保 Dog 等子类字段满足可访问要求(默认 public 字段或配有 getter)。
  • 由于未启用 @J

    sonTypeInfo(如 @JsonTypeInfo(use = JsonTypeInfo.Id.NAME)),Jackson 在反序列化时无法自动识别 标签对应的具体子类类型。若需反序列化 XML 回 Zoo 对象,必须配套实现自定义 JsonDeserializer,解析 XML 元素名并手动实例化对应子类。
  • 若项目允许,更推荐使用 Jackson 内置的多态支持(如 @JsonTypeInfo + @JsonSubTypes),可避免手写序列化/反序列化器,提升可维护性与健壮性。

总之,writeObjectField() 是连接自定义结构控制与默认序列化能力的关键桥梁——它让你掌控“在哪里写”,而把“怎么写内容”交还给 Jackson,兼顾灵活性与完整性。


# js  # json  # app  # String  # Object  # 多态  # 子类  # xml  # public  # 委托  # 对象  # 序列化  # 自定义  # 让你  # 尤其是  # 推荐使用  # 自动识别  # 跳过  # 而把 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Laravel Facade的原理是什么_深入理解Laravel门面及其工作机制  如何注册花生壳免费域名并搭建个人网站?  Laravel Blade模板引擎语法_Laravel Blade布局继承用法  无锡营销型网站制作公司,无锡网选车牌流程?  详解免费开源的DotNet二维码操作组件ThoughtWorks.QRCode(.NET组件介绍之四)  Laravel Eloquent关联是什么_Laravel模型一对一与一对多关系精讲  html5源代码发行怎么设置权限_访问权限控制方法与实践【指南】  Laravel模型事件有哪些_Laravel Model Event生命周期详解  Laravel如何使用Spatie Media Library_Laravel图片上传管理与缩略图生成【步骤】  零服务器AI建站解决方案:快速部署与云端平台低成本实践  Laravel如何使用软删除(Soft Deletes)功能_Eloquent软删除与数据恢复方法  如何用好域名打造高点击率的自主建站?  深圳防火门网站制作公司,深圳中天明防火门怎么编码?  如何用免费手机建站系统零基础打造专业网站?  如何用PHP快速搭建CMS系统?  Laravel如何使用Gate和Policy进行权限控制_Laravel权限判定与策略规则配置  UC浏览器如何设置启动页 UC浏览器启动页设置方法  Windows Hello人脸识别突然无法使用  jquery插件bootstrapValidator表单验证详解  Linux虚拟化技术教程_KVMQEMU虚拟机安装与调优  如何快速生成橙子建站落地页链接?  谷歌Google入口永久地址_Google搜索引擎官网首页永久入口  网站制作壁纸教程视频,电脑壁纸网站?  javascript和jQuery中的AJAX技术详解【包含AJAX各种跨域技术】  弹幕视频网站制作教程下载,弹幕视频网站是什么意思?  EditPlus 正则表达式 实战(3)  Windows10怎样连接蓝牙设备_Windows10蓝牙连接步骤【教程】  Python文件操作最佳实践_稳定性说明【指导】  html5如何设置样式_HTML5样式设置方法与CSS应用技巧【教程】  使用spring连接及操作mongodb3.0实例  实现点击下箭头变上箭头来回切换的两种方法【推荐】  Laravel如何使用Gate和Policy进行授权?(权限控制)  如何利用DOS批处理实现定时关机操作详解  JavaScript如何实现路由_前端路由原理是什么  Laravel storage目录权限问题_Laravel文件写入权限设置  合肥制作网站的公司有哪些,合肥聚美网络科技有限公司介绍?  如何在局域网内绑定自建网站域名?  儿童网站界面设计图片,中国少年儿童教育网站-怎么去注册?  Laravel路由Route怎么设置_Laravel基础路由定义与参数传递规则【详解】  html如何与html链接_实现多个HTML页面互相链接【互相】  JS中对数组元素进行增删改移的方法总结  如何基于PHP生成高效IDC网络公司建站源码?  黑客如何通过漏洞一步步攻陷网站服务器?  Laravel如何使用.env文件管理环境变量?(最佳实践)  JavaScript模板引擎Template.js使用详解  bing浏览器学术搜索入口_bing学术文献检索地址  制作无缝贴图网站有哪些,3dmax无缝贴图怎么调?  Laravel怎么生成URL_Laravel路由命名与URL生成函数详解  使用Dockerfile构建java web环境  Laravel中的withCount方法怎么高效统计关联模型数量