Jackson: add suffix according to a field type

Viewed 230

Here my POJO:

public class AutorDenormalized {

    private String id;
    private Long unitatId;
    private String grupId;
    private String descripcio;

    public AutorDenormalized() {

    }

    // getters $ setters

}

I'd like to serialise this kind of objects adding a suffix according to field type. I mean,

  • If field type is a String -> then add a *_s suffix
  • If field type is a Long -> then add a *_l suffix
  • Otherwise keep going

Do you have any ideas how to solve it?

2 Answers

You need to implement custom BeanPropertyWriter which can generate property name with a suffix. To register custom BeanPropertyWriter you need to create custom BeanSerializerModifier.

Below example shows simplified implementation which shows a way how to achieve above result:

import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import com.fasterxml.jackson.databind.util.NameTransformer;

import java.io.IOException;
import java.util.List;

public class JsonTypeInfoApp {

    public static void main(String[] args) throws IOException {
        SimpleModule typeSuffixModule = new SimpleModule();
        typeSuffixModule.setSerializerModifier(new TypeSuffixBeanSerializerModifier());

        ObjectMapper mapper = new ObjectMapper();
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        mapper.registerModule(typeSuffixModule);

        System.out.println(mapper.writeValueAsString(new AutorDenormalized()));
    }
}

class TypeSuffixBeanSerializerModifier extends BeanSerializerModifier {

    @Override
    public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
        for (int i = 0; i < beanProperties.size(); ++i) {
            final BeanPropertyWriter writer = beanProperties.get(i);
            Class<?> rawType = writer.getType().getRawClass();
            if (supports(rawType)) {
                final String suffix = constructSuffix(rawType);

                beanProperties.set(i, writer.rename(NameTransformer.simpleTransformer(null, suffix)));
            }
        }
        return beanProperties;
    }

    private String constructSuffix(Class<?> rawType) {
        return "_" + Character.toLowerCase(rawType.getSimpleName().charAt(0));
    }

    private boolean supports(Class<?> rawClass) {
        return rawClass == String.class || rawClass == Long.class;
    }
}

Above code prints:

{
  "id_s" : "1",
  "unitatId_l" : 123,
  "grupId_s" : "2",
  "descripcio_s" : "3"
}

See also:

Aside from the accepted answer, which works fine, you could also consider implementing PropertyNameStrategy: it would let you rename properties and gets field, setter/getter, creator parameter (which you need to find type of property). Might be little bit less work.

Related