如何使用jackson以不同方式序列化同一实体的相同属性

时间:2014-08-05 11:46:13

标签: java json serialization jackson

假设你有这个实体:

class Foo{
 String propA;
 String propB;
}

并且您希望序列化一个API,如:

{propA: "ola",
 propB: "Holla"}

以及其他API,例如:

{fooPropA: "ola",
 fooPropB: "Holla"}

如何使用jackson和使用相同的实体来实现这一目标。创建2个不同的实体不是一种选择:)

2 个答案:

答案 0 :(得分:1)

有几种方法可以实现这一目标。您可以启用自定义序列化程序(已由@se_vedem涵盖),注册注释introspector,该注释会更改相应类的属性名称,依此类推。

但是,如果您只愿意为所有属性名称添加字符串前缀,那么the Jackson property name strategy可能是最合适的。命名策略类可以访问序列化对象类型信息,因此您可以决定是否更改属性名称。

以下是使用定义前缀的自定义注释的示例:

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"}

在您的API方法中,您可以选择两个ObjectMapper实例,其中一个具有默认命名命名策略,另一个具有自定义命名策略。

答案 1 :(得分:0)

您可以使用Jackson的模块功能实现这一目标。

基本上,每个API都有自己的ObjectMapper,并且它们将配置不同的模块。这样,您可以为同一个类创建2个序列化程序,并在相应的模块上注册它们。可在此处找到更多阅读http://wiki.fasterxml.com/JacksonFeatureModules

但是,请注意序列化程序按特定顺序加载。首先,它尝试获取带注释的那些,如果没有找到,它将尝试从模块中注册那些。因此,例如,如果您的类使用序列化程序进行注释,那么将选择该序列化程序(FooSerializer)而不是模块中配置的类(MySecondFooSerializer)。

@JsonSerialize(using = FooSerializer.class)
class Foo{
 String propA;
 String propB;
}

module.addSerializer(Foo.class, new MySecondFooSerializer());