在多个 Jackson 映射器之间创建唯一配置

Create Unique Configuration between multiple Jackson mappers

Jackson 中是否有任何接口,或为多个对象映射器创建相同配置的更好方法? 例如,我有这两种方法用于相同的 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();
    }
  }
}

并且两者的配置完全相同,如果将来我需要一种新格式,我可能会使用相同的配置。

要定义 MixIn 和自定义 serialisers/deserialisers,您可以使用 SimpleModule。对于 ObjectMapper 上的 enabling/disabling 个功能,您可以创建一个方法。

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

简单用法:

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

以上代码打印:

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

另请参阅:

  • Should I declare Jackson's ObjectMapper as a static field?
  • How do I correctly reuse Jackson ObjectMapper?