javajacksonexport-to-csvobjectmapperxmlmapper

Create Unique Configuration between multiple Jackson mappers


Is there any interface in Jackson, or a better way to create the same configuration for multiple object mappers? For example, I have this both methods for the same class:

public static File toCsv(List<Entity> entityList) {

    final File tempFile = new File(CSV_FILE_NAME);
    tempFile.deleteOnExit();

    CsvMapper mapper = new CsvMapper();
    mapper.findAndRegisterModules()
        .configure(JsonGenerator.Feature.IGNORE_UNKNOWN, true)
        .addMixIn(Entity.class, EntityMixIn.class)
        .addMixIn(EntityB.class, EntityBMixIn.class);
      CsvSchema schema = mapper.schemaFor(Entity.class).withHeader();

    try {
      mapper.writer(schema).writeValue(tempFile,entityList);
      return tempFile;

    } catch (IOException ex) {
      throw new Exception();
    }
  }
}
public static File toXml(List<Entity> entityList) {

    final File tempFile = new File(XML_FILE_NAME);
    tempFile.deleteOnExit();

    XmlMapper mapper = new XmlMapper();
    mapper.findAndRegisterModules()
        .configure(JsonGenerator.Feature.IGNORE_UNKNOWN, true)
        .addMixIn(Entity.class, EntityMixIn.class)
        .addMixIn(EntityB.class, EntityBMixIn.class);

    try {
      mapper.writeValue(tempFile, entityList);
      return tempFile;

    } catch (IOException ex) {
      throw new Exception();
    }
  }
}

And both have exactly the same configuration, if in the future i need a new format, i could probably use the same configuration.


Solution

  • For defining MixIn and custom serialisers/deserialisers you can use SimpleModule. For enabling/disabling features on ObjectMapper you can create a method.

    class MapperFactory {
    
      private final ObjectMapper jsonMapper = configure(new ObjectMapper());
      private final XmlMapper xmlMapper = configure(new XmlMapper());
      private final CsvMapper csvMapper = configure(new CsvMapper());
    
      public ObjectMapper getJsonMapper() {
        return jsonMapper;
      }
    
      public XmlMapper getXmlMapper() {
        return xmlMapper;
      }
    
      public CsvMapper getCsvMapper() {
        return csvMapper;
      }
    
      public <T extends ObjectMapper> T configure(T mapper) {
        // configure mapper instance if required
        mapper.enable(JsonGenerator.Feature.IGNORE_UNKNOWN);
        // register default
        mapper.findAndRegisterModules();
        // register custom
        mapper.registerModule(createCustomModule());
    
        return mapper;
      }
    
      public SimpleModule createCustomModule() {
        SimpleModule module = new SimpleModule("EntityMixIns");
        module.setMixInAnnotation(Entity.class, EntityMixIn.class);
        // more MixIns
    
        return module;
      }
    }
    

    Simple usage:

    import com.fasterxml.jackson.annotation.JsonProperty;
    import com.fasterxml.jackson.core.JsonGenerator;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.module.SimpleModule;
    import com.fasterxml.jackson.dataformat.csv.CsvMapper;
    import com.fasterxml.jackson.dataformat.csv.CsvSchema;
    import com.fasterxml.jackson.dataformat.xml.XmlMapper;
    
    public class JsonApp {
    
      public static void main(String[] args) throws Exception {
        MapperFactory mapperFactory = new MapperFactory();
    
        System.out.println("JSON:");
        System.out.println(mapperFactory.getJsonMapper().writeValueAsString(new Entity()));
    
        System.out.println("XML:");
        System.out.println(mapperFactory.getXmlMapper().writeValueAsString(new Entity()));
    
        System.out.println("CSV:");
        CsvMapper csvMapper = mapperFactory.getCsvMapper();
        CsvSchema schema = csvMapper.schemaFor(Entity.class).withHeader();
        System.out.println(csvMapper.writer(schema).writeValueAsString(new Entity()));
      }
    }
    
    class Entity {
      private int id = 12;
    
      public int getId() {
        return id;
      }
    
      public void setId(int id) {
        this.id = id;
      }
    
      @Override
      public String toString() {
        return "A{" + "id=" + id + '}';
      }
    }
    
    interface EntityMixIn {
    
      @JsonProperty("_idName")
      int getId();
    }
    

    Above code prints:

    JSON:
    {"_idName":12}
    XML:
    <Entity><_idName>12</_idName></Entity>
    CSV:
    _idName
    12
    

    See also: