Jackson:如何在不修改 POJO 的情况下将现有的 属性 编辑为 JSON?
Jackson: How to edit existing property to the JSON without modifying the POJO?
我需要在 POJO 中编辑 "existing field" 的名称,而不是添加 "extra_field"。下面引用 link 的方法是否可行?
请注意我不想使用 @JsonProperty
注释。
要求是,我有一个 POJO 并且希望每次都使用不同的字段名称而不更改 POJO。例如,我在 POJO 中有一个字段 c_id
,有时它需要写成 cust_id
而另一次它会是 my_id
.
另请注意,我无法更改 POJO 的实现,因为它已在多个模块中使用并且具有通用实现。
POJO 示例:
class MyPojo {
String id;
// getter and setters
}
预期输出如下:(可以更改字段名称)
- {"cust_id": "123"}
- {"my_id": "123"}
混合
在不向原始 POJO 添加注释的情况下修改 Jackson 输出的最简单方法是使用混合。
只需定义一个带有必要注释的 mixin-class 并向 Jackson 表明您希望在序列化原始对象时使用该 mixin。
private static class MyPojoMixin {
@JsonProperty("cust_id")
private String id;
}
public String serializeWithMixin(MyPojo p) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(MyPojo.class, MyPojoMixin.class);
return mapper.writeValueAsString(p);
}
自定义属性命名策略
如果您需要以编程方式更改字段名称,您可能无法使用 mixin 解决方案。然后您可以使用自定义 PropertyNamingStrategy:
public class IdRenamingStrategy extends PropertyNamingStrategy {
private final PropertyNamingStrategy inner;
private final String newIdPropertyName;
public IdRenamingStrategy(String newIdPropertyName) {
this(PropertyNamingStrategy.LOWER_CAMEL_CASE, newIdPropertyName);
}
public IdRenamingStrategy(PropertyNamingStrategy inner, String newIdPropertyName) {
this.inner = inner;
this.newIdPropertyName = newIdPropertyName;
}
private String translate(String propertyName) {
if ("id".equals(propertyName)) {
return newIdPropertyName;
} else {
return propertyName;
}
}
@Override
public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) {
return inner.nameForField(config, field, translate(defaultName));
}
@Override
public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return inner.nameForGetterMethod(config, method, translate(defaultName));
}
@Override
public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return inner.nameForSetterMethod(config, method, translate(defaultName));
}
@Override
public String nameForConstructorParameter(MapperConfig<?> config, AnnotatedParameter ctorParam, String defaultName) {
return inner.nameForConstructorParameter(config, ctorParam, translate(defaultName));
}
}
可以这样使用:
public String serializeWithPropertyNamingStrategy(MyPojo p) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(new IdRenamingStrategy("cust_id"));
return mapper.writeValueAsString(p));
}
我需要在 POJO 中编辑 "existing field" 的名称,而不是添加 "extra_field"。下面引用 link 的方法是否可行?
请注意我不想使用 @JsonProperty
注释。
要求是,我有一个 POJO 并且希望每次都使用不同的字段名称而不更改 POJO。例如,我在 POJO 中有一个字段 c_id
,有时它需要写成 cust_id
而另一次它会是 my_id
.
另请注意,我无法更改 POJO 的实现,因为它已在多个模块中使用并且具有通用实现。
POJO 示例:
class MyPojo {
String id;
// getter and setters
}
预期输出如下:(可以更改字段名称)
- {"cust_id": "123"}
- {"my_id": "123"}
混合
在不向原始 POJO 添加注释的情况下修改 Jackson 输出的最简单方法是使用混合。
只需定义一个带有必要注释的 mixin-class 并向 Jackson 表明您希望在序列化原始对象时使用该 mixin。
private static class MyPojoMixin {
@JsonProperty("cust_id")
private String id;
}
public String serializeWithMixin(MyPojo p) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(MyPojo.class, MyPojoMixin.class);
return mapper.writeValueAsString(p);
}
自定义属性命名策略
如果您需要以编程方式更改字段名称,您可能无法使用 mixin 解决方案。然后您可以使用自定义 PropertyNamingStrategy:
public class IdRenamingStrategy extends PropertyNamingStrategy {
private final PropertyNamingStrategy inner;
private final String newIdPropertyName;
public IdRenamingStrategy(String newIdPropertyName) {
this(PropertyNamingStrategy.LOWER_CAMEL_CASE, newIdPropertyName);
}
public IdRenamingStrategy(PropertyNamingStrategy inner, String newIdPropertyName) {
this.inner = inner;
this.newIdPropertyName = newIdPropertyName;
}
private String translate(String propertyName) {
if ("id".equals(propertyName)) {
return newIdPropertyName;
} else {
return propertyName;
}
}
@Override
public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) {
return inner.nameForField(config, field, translate(defaultName));
}
@Override
public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return inner.nameForGetterMethod(config, method, translate(defaultName));
}
@Override
public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return inner.nameForSetterMethod(config, method, translate(defaultName));
}
@Override
public String nameForConstructorParameter(MapperConfig<?> config, AnnotatedParameter ctorParam, String defaultName) {
return inner.nameForConstructorParameter(config, ctorParam, translate(defaultName));
}
}
可以这样使用:
public String serializeWithPropertyNamingStrategy(MyPojo p) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(new IdRenamingStrategy("cust_id"));
return mapper.writeValueAsString(p));
}