JsonUnwrapped prefix & camel case properties

820 views
Skip to first unread message

Drpbxa

unread,
Jul 31, 2017, 6:56:59 PM7/31/17
to jackson-user
When you annotate a property with @JsonUnwrapped you can add a prefix attribute. For example:

@JsonUnwrapped(prefix="camel")
MyObject obj;

If MyObject has a property "casedProperty", the json key will be "camelcasedProperty" instead of "camelCasedProperty". I found a way to display the json keys the way I wanted. What I did was registering a module with a serializer modifier like this:

public class MySerializerModifier extends BeanSerializerModifier {
    @Override
    public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> serializer) {
        return new MySerializer(serializer);
    }
}

The new serializer takes the original serializer as a parameter and most of the time it just delegates to it except for the unwrappingSerializer method, in which it chains the NameTransformer parameter with a new transformer that capitalizes the first character in the name before delegating to the original serializer:

public class MySerializer<T> extends JsonSerializer<T> {
    private final JsonSerializer<T> defaultSerializer;

    public MySerializer(JsonSerializer<T> defaultSerializer) {
        this.defaultSerializer = defaultSerializer;
    }

    @Override
    public void serialize(T t, JsonGenerator gen, SerializerProvider provider) throws IOException {
        defaultSerializer.serialize(t, gen, provider);
    }

    @Override
    public JsonSerializer<T> unwrappingSerializer(NameTransformer unwrapper) {
        return defaultSerializer.unwrappingSerializer(NameTransformer.chainedTransformer(unwrapper, new CapitalizeTransformer()));
    }

    private static class CapitalizeTransformer extends NameTransformer {
        @Override
        public String transform(String name) {
            return StringUtils.capitalize(name);
        }

        @Override
        public String reverse(String transformed) {
            return StringUtils.uncapitalize(transformed);
        }
    }

    @Override
    public JsonSerializer<T> replaceDelegatee(JsonSerializer<?> delegatee) {
        return defaultSerializer.replaceDelegatee(delegatee);
    }

    @Override
    public void serializeWithType(T value, JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSer) throws IOException {
        defaultSerializer.serializeWithType(value, gen, serializers, typeSer);
    }

    @Override
    public Class<T> handledType() {
        return defaultSerializer.handledType();
    }

    @Override
    public boolean isEmpty(T value) {
        return defaultSerializer.isEmpty(value);
    }

    @Override
    public boolean isEmpty(SerializerProvider provider, T value) {
        return defaultSerializer.isEmpty(provider, value);
    }

    @Override
    public boolean usesObjectId() {
        return defaultSerializer.usesObjectId();
    }

    @Override
    public boolean isUnwrappingSerializer() {
        return defaultSerializer.isUnwrappingSerializer();
    }

    @Override
    public JsonSerializer<?> getDelegatee() {
        return defaultSerializer.getDelegatee();
    }

    @Override
    public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType type) throws JsonMappingException {
        defaultSerializer.acceptJsonFormatVisitor(visitor, type);
    }
}

My questions are: is there a more straightforward way to achieve what I want? are there any drawbacks in the current approach? Is there a way to provide a custom NameTransformer that does not involve serializer modifiers?

Thank you.

Tatu Saloranta

unread,
Aug 2, 2017, 8:08:49 PM8/2/17
to jackson-user
Approach seems reasonable; there isn't anything to achieve combination
of renaming and unwrapping using other mechanisms.
Simple renaming (adding prefix, modifying base) would be simple to do
with different method of BeanSerializerModifier, but unwrapping part
requires separate handling.

-+ Tatu +-
Reply all
Reply to author
Forward
0 new messages