Java 如何使用jackson以不同方式序列化同一实体的相同属性
假设您有这个实体:Java 如何使用jackson以不同方式序列化同一实体的相同属性,java,json,serialization,jackson,Java,Json,Serialization,Jackson,假设您有这个实体: class Foo{ String propA; String propB; } 您希望序列化一个API,如: {propA: "ola", propB: "Holla"} 对于另一个API,如: {fooPropA: "ola", fooPropB: "Holla"} 如何使用jackson和使用相同的实体来实现这一点。创建两个不同的实体不是一个选项:)您可以通过使用Jackson的模块功能来实现这一点。 基本上,每个API都有自己的ObjectMapper,
class Foo{
String propA;
String propB;
}
您希望序列化一个API,如:
{propA: "ola",
propB: "Holla"}
对于另一个API,如:
{fooPropA: "ola",
fooPropB: "Holla"}
如何使用jackson和使用相同的实体来实现这一点。创建两个不同的实体不是一个选项:)您可以通过使用Jackson的模块功能来实现这一点。
基本上,每个API都有自己的ObjectMapper,并将配置不同的模块。通过这种方式,您可以为同一个类创建2个序列化程序,并将它们注册到相应的模块上。更多阅读可以在这里找到 但是,请注意序列化程序是按特定顺序加载的。首先,它尝试获取带注释的,如果没有找到,它将尝试从模块中获取已注册的。所以,例如,若您用serializer对类进行注释,那个么将选择该序列化器(FooSerializer),而不是在模块中配置的序列化器(MySecondFooSerializer)
有几种方法可以实现这一点。您可以启用自定义序列化程序(已在@se_vedem中介绍)、注册注释以更改相应类的属性名称等等 但是,如果您只想在所有属性名称中添加字符串前缀,那么可能是最合适的。命名策略类可以访问序列化对象类型信息,因此您可以决定是否更改属性名称 以下是使用自定义注释定义前缀的示例:
public class JacksonNameStrategy {
@Retention(RetentionPolicy.RUNTIME)
public static @interface PropertyPrefix {
String value();
}
@PropertyPrefix("foo_")
public static class Foo {
public String propA;
public String propB;
public Foo(String propA, String propB) {
this.propA = propA;
this.propB = propB;
}
}
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(new MyPropertyNamingStrategyBase());
System.out.println(mapper.writeValueAsString(new Foo("old", "Holla")));
}
private static class MyPropertyNamingStrategyBase extends PropertyNamingStrategy {
@Override
public String nameForField(MapperConfig<?> config,
AnnotatedField field,
String defaultName) {
PropertyPrefix ann = field.getDeclaringClass().getAnnotation(PropertyPrefix.class);
if (ann != null) {
return ann.value() + defaultName;
}
return super.nameForField(config, field, defaultName);
}
}
}
在API方法中,您可以在两个
ObjectMapper
实例中进行选择,一个使用默认命名策略,另一个使用自定义命名策略。好提示,但这会影响该ObjectMapper序列化的所有实体。我一直在寻找一种隔离某些实体的方法,比如100个实体中只有2个需要这种特殊的序列化处理。@sa_vedem您想如何区分这些实体?基于类型信息或属性值?一个将使用ObjectMapperA序列化,另一个使用ObjectMapperB@sa_vedem所以通过ObjetMapper影响所有实体是可以的,对吧?对不起,我在你的第一个问题上回答得很糟糕。我想在类型信息上区分它们。
public class JacksonNameStrategy {
@Retention(RetentionPolicy.RUNTIME)
public static @interface PropertyPrefix {
String value();
}
@PropertyPrefix("foo_")
public static class Foo {
public String propA;
public String propB;
public Foo(String propA, String propB) {
this.propA = propA;
this.propB = propB;
}
}
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(new MyPropertyNamingStrategyBase());
System.out.println(mapper.writeValueAsString(new Foo("old", "Holla")));
}
private static class MyPropertyNamingStrategyBase extends PropertyNamingStrategy {
@Override
public String nameForField(MapperConfig<?> config,
AnnotatedField field,
String defaultName) {
PropertyPrefix ann = field.getDeclaringClass().getAnnotation(PropertyPrefix.class);
if (ann != null) {
return ann.value() + defaultName;
}
return super.nameForField(config, field, defaultName);
}
}
}
{"foo_propA":"old","foo_propB":"Holla"}