How to serialize differently the same properties of the same object using jackson

Let's assume you have this object:

class Foo{
 String propA;
 String propB;
}

      

and you want to serialize for one API like:

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

      

and for another API, for example:

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

      

How can this be achieved with jackson and using the same object. Making two different objects is not an option :)

+3


source to share


2 answers


There are several ways to achieve this. You can enable a custom serializer (already covered by @se_vedem), register an introspector annotation that changes the property names for the corresponding class, and so on to.

However, if you only want to add a string prefix to all property names, then the property name strategy in Jackson is probably the best fit. The naming strategy class has access to information about the types of serialized objects, so you can decide whether to change the property name or not.

Here's an example using a custom annotation that defines a prefix:

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);
        }
    }
}

      



Output:

{"foo_propA":"old","foo_propB":"Holla"}

      

In your API method, you choose between two instances, ObjectMapper

one with a default naming strategy and one with a custom one.

+1


source


You can achieve this using a module function from Jackson.

Basically, each API will have its own ObjectMapper and they will be configured with different modules. This way you can create 2 serializers for the same class and register them in the appropriate module. Read more here http://wiki.fasterxml.com/JacksonFeatureModules



Remember, however, that serializers are loaded in a specific order. First it tries to get annotated ones, if not found it will try to get registered ones from modules. So, for example, if you have a class annotated with a serializer, then that serializer (FooSerializer) will be selected instead of the one configured in the module (MySecondFooSerializer).

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

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

      

0


source







All Articles