Jackson反序列化时@JsonUnwrapped注解失效问题求助
解决Jackson反序列化@JsonUnwrapped忽略_l10n字段的问题
问题核心
用@JsonUnwrapped配合自定义序列化器实现了LocalizedField的拆包序列化(将value和value_l10n映射为xxx和xxx_l10n),但反序列化时自定义反序列化器只能拿到xxx节点,无法获取xxx_l10n数据,还需额外添加@JsonIgnoreProperties才能执行逻辑。
解决方案
核心思路是通过ContextualDeserializer获取当前字段的名称,从而拼接出对应的xxx_l10n键名,再从父节点中同时读取两个字段的数据。
1. 实现带上下文感知的反序列化器
让自定义反序列化器实现ContextualDeserializer接口,在初始化时获取当前字段的名称,反序列化时从父节点中读取xxx和xxx_l10n两个节点:
public class LocalizedFieldDeserializer extends JsonDeserializer<LocalizedField> implements ContextualDeserializer { private String fieldName; @Override public LocalizedField deserialize(JsonParser parser, DeserializationContext ctx) throws IOException { // 获取父节点(包含当前字段的xxx和xxx_l10n) JsonNode parentNode = parser.getParsingContext().getParent().getCurrentNode(); // 读取基础值 String value = parentNode.get(fieldName).asText(); // 读取多语言映射 JsonNode l10nNode = parentNode.get(fieldName + "_l10n"); Map<String, String> l10nMap = null; if (l10nNode != null && l10nNode.isObject()) { l10nMap = ctx.readValue(l10nNode.traverse(), new TypeReference<Map<String, String>>() {}); } return new LocalizedField(value, l10nMap); } @Override public JsonDeserializer<?> createContextual(DeserializationContext ctx, BeanProperty property) throws JsonMappingException { LocalizedFieldDeserializer deserializer = new LocalizedFieldDeserializer(); // 保存当前字段的名称(如name、description) deserializer.fieldName = property.getName(); return deserializer; } }
2. 配置LocalizedField类
在LocalizedField上绑定自定义反序列化器,同时保留JPA@Embeddable注解:
@Embeddable @JsonDeserialize(using = LocalizedFieldDeserializer.class) public class LocalizedField { private String value; @JsonProperty("value_l10n") private Map<String, String> valueL10n; // 构造函数、getter/setter省略 }
3. 实体类中使用@JsonUnwrapped
在包含LocalizedField的实体类字段上保留@JsonUnwrapped,无需再添加@JsonIgnoreProperties:
@Entity public class Product { @Id private Long id; @JsonUnwrapped private LocalizedField name; @JsonUnwrapped private LocalizedField description; // 构造函数、getter/setter省略 }
原理说明
ContextualDeserializer能在反序列化时获取当前字段的名称,从而动态找到对应的xxx_l10n节点;- 从父节点读取数据,能一次性获取拆包后的两个字段,避免了单个节点的限制;
- 该方案完全兼容JPA
@Embeddable,可在多个实体类中复用LocalizedField。
内容的提问来源于stack exchange,提问作者Kariem
相关产品推荐
相关产品推荐

