
使用 jackson 的 `jackson-dataformat-xml` 序列化 java 对象为 xml 时,若嵌套对象字段未显式初始化,即使其内部字段声明了默认值,也不会被自动实例化,导致 xml 中仅出现空标签(如 `
在 Jackson(包括 XmlMapper)的序列化过程中,字段是否参与序列化,取决于该字段引用的对象是否为 null,而非其类中成员变量是否设置了默认值。也就是说:即使 SettingsBlock 的 block1 和 block2 在类定义中声明了 = true 和 = false,只要 Settings.settingsBlock 字段本身为 null,Jackson 就不会尝试访问或序列化其任何属性——最终只输出一个空的
✅ 正确做法是:在父类中为嵌套对象字段提供非 null 的默认实例。例如:
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
public class Settings {
private SettingsBlock settingsBlock = new SettingsBlock(); // ✅ 关键:主动初始化
private int test1 = 10;
private int test2;
}同时确保嵌套类 SettingsBlock 的字段默认值定义正确(注意原问题中 block2= 存在语法错误,应补全):
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
public class SettingsBlock {
private Boolean block1 = true; // ✅ 默认 true
private Boolean block2 = false; // ✅ 修复语法:不能写成 `=;`
}构建 XML 的代码也需注意细节:XmlMapper 实例应启用 DEFAULT_USE_EQUALITY_FOR_DEFAULTS 或更推荐的方式是配置 SerializationFeature.WRITE_NULL_MAP_VALUES 等(但本例核心是对象非空),且建议启用 XmlMapper 的默认缩进以提升可读性:
XmlMapper xmlMapper = new XmlMapper(); xmlMapper.enable(SerializationFeature.INDENT_OUTPUT); // 可选:美化输出 Settings settings = new Settings(); // 使用无参构造,settingsBlock 已被初始化 String xml = xmlMapper.writeValueAsString(settings); System.out.println(xml);
输出即符合预期:
true false 10 0
⚠️ 注意事项:
- Lombok 的 @NoArgsConstructor 不会执行字段初始化语句(如 = new SettingsBlock()),它仅生成无参构造函数;因此字段初始化必须显式写在声明处(如上所示)。
- 若使用 @Builder,可通过 @Builder.Default 实现 Builder 模式下的默认值(适用于构建时动态控制),但普通 new Settings() 仍依赖字段级初始化。
- 如需全局统一处理未初始化嵌套对象,可自定义 ContextualSerializer,但对多数场景而言,显式初始化是最清晰、高效且符合 Jackson 设计哲学的方式。
总结:Jackson 序列化遵循“有对象才序列化其属性”的原则。要让嵌套对象的默认值出现在 XML 中,务必确保其引用本身不为 null——这是解决问题的根本所在。










