首页 > 解决方案 > 考虑到性能,我应该如何获得用于将 POJO 序列化为 JSON 的 ObjectWriter?

问题描述

com.fasterxml.jackson.databind.ObjectMapper JavaDocs说:

映射器实例是完全线程安全的,前提是实例的所有配置都发生在任何读取或写入调用之前。如果映射器实例的配置在第一次使用后被修改,更改可能会或可能不会生效,并且配置调用本身可能会失败。如果您需要使用不同的配置,您有两种主要可能性:

构造并使用 ObjectReader 进行读取,使用 ObjectWriter 进行写入。这两种类型都是完全不可变的,您可以使用 ObjectMapper 的工厂方法或读取器/写入器本身自由地创建具有不同配置的新实例。新的 ObjectReaders 和 ObjectWriters 的构造是一个非常轻量级的操作,因此通常适合根据需要在每次调用的基础上创建它们,以配置诸如 JSON 的可选缩进之类的东西。

每次我需要一个新的 ObjectWriter 时都可以拨打这个电话吗?

jsonString = new MyObjectWriter().objectWriter().writeValueAsString(myPojo);

MyObjectWriter 看起来像这样:

public class MyObjectWriter {
    public ObjectWriter objectWriter()
    {
        return new ObjectMapper()
                .writer()
                .with(SerializationFeature.INDENT_OUTPUT)
                .with(JsonGenerator.Feature.IGNORE_UNKNOWN);
    }
}

我应该保留 ObjectMapper 的副本吗?对象编写器?

标签: javajsonserializationjacksonjackson-databind

解决方案


就像文档说的那样,这是非常便宜的操作,您可以“根据通话”进行操作。让我们看看每种方法背后都有什么。

  • ObjectMapper.writerObjectWriter-使用SerializationConfigfrom创建新的ObjectMapper
  • ObjectWriter.with- 创建ObjectWriter基于caller实例的新功能以及必须启用的新功能。如果给定功能已启用,则返回相同的实例。如果功能更改配置 -ObjectWriter创建并返回新的。

让我们看看显示给定场景的示例应用程序:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.SerializationFeature;

import java.util.Collections;
import java.util.Map;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        ObjectWriter writer0 = mapper.writer();
        ObjectWriter writer1 = writer0.with(SerializationFeature.INDENT_OUTPUT);
        ObjectWriter writer2 = writer1.with(SerializationFeature.INDENT_OUTPUT);
        ObjectWriter writer3 = writer2.with(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS);

        Map<String, Long> map = Collections.singletonMap("key", 123L);
        System.out.println(writer0 + " = " + writer0.writeValueAsString(map));
        System.out.println(writer1 + " = " + writer1.writeValueAsString(map));
        System.out.println(writer2 + " = " + writer2.writeValueAsString(map));
        System.out.println(writer3 + " = " + writer3.writeValueAsString(map));


        ObjectMapper mapper1 = new ObjectMapper();
        mapper1.enable(SerializationFeature.INDENT_OUTPUT);
        mapper1.enable(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS);

        ObjectWriter writer4 = mapper1.writer();
        System.out.println(writer4 + " = " + writer4.writeValueAsString(map));
    }
}

上面的应用程序打印:

com.fasterxml.jackson.databind.ObjectWriter@2ed94a8b = {"key":123}
com.fasterxml.jackson.databind.ObjectWriter@2a5ca609 = {
  "key" : 123
}
com.fasterxml.jackson.databind.ObjectWriter@2a5ca609 = {
  "key" : 123
}
com.fasterxml.jackson.databind.ObjectWriter@20e2cbe0 = {
  "key" : "123"
}

com.fasterxml.jackson.databind.ObjectWriter@68be2bc2 = {
  "key" : "123"
}

请注意,第二个 ( writer1) 和第三个 ( writer2) 实例 ( com.fasterxml.jackson.databind.ObjectWriter@2a5ca609) 是相同的。它们还生成相同的JSON有效载荷。

因此,使用ObjectMapper我们创建和配置的第一个实例ObjectWriter。但主要只使用最后一个。中间的一切都已经过去了,等待收集GC。这样做没有意义。最好通过调用方法创建ObjectMapper实例,配置它并创建已经配置的实例。您可以为配置的实例创建-like 类,并且可以使用这些实例生成-s。ObjectWriterwriter()FactoryObjectMapperObjectWriter


推荐阅读