Spring boot与Jackson ObjectMapper

Spring Boot支持与三种JSON mapping库集成:Gson、Jackson和JSON-B。Jackson是首选和默认的。

Jackson是spring-boot-starter-json的一部分,spring-boot-starter-web中包含spring-boot-starter-json。也就是说,当项目中引入spring-boot-starter-web后会自动引入spring-boot-starter-json。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

ObjectMapper

ObjectMapper是jackson-databind包中的一个类,提供读写JSON的功能,可以方便的进行对象和JSON转换:

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;

public final class JsonUtil {
    private static ObjectMapper mapper = new ObjectMapper();

    private JsonUtil() {
    }

    /**
     * Serialize any Java value as a String.
     */
    public static String generate(Object object) throws JsonProcessingException {
        return mapper.writeValueAsString(object);
    }

    /**
     * Deserialize JSON content from given JSON content String.
     */
    public static <T> T parse(String content, Class<T> valueType) throws IOException {
        return mapper.readValue(content, valueType);
    }
}

编写一简单POJO测试类:

import java.util.Date;

public class Hero {

    public static void main(String[] args) throws Exception {
        System.out.println(JsonUtil.generate(new Hero("Jason", new Date())));
    }

    private String name;

    private Date birthday;

    public Hero(String name, Date birthday) {
        this.name = name;
        this.birthday = birthday;
    }

    public String getName() {
        return name;
    }

    public Date getBirthday() {
        return birthday;
    }
}

运行后输出结果如下:

{"name":"Jason","birthday":1540909420353}

可以看到日期转换为长整型。

ObjectMapper默认序列化配置启用了SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,日期将转换为长整型。可查看如下源码:

public ObjectMapper(JsonFactory jf, DefaultSerializerProvider sp, DefaultDeserializationContext dc) {
...
    BaseSettings base = DEFAULT_BASE.withClassIntrospector(defaultClassIntrospector());
    _configOverrides = new ConfigOverrides();
    _serializationConfig = new SerializationConfig(base, _subtypeResolver, mixins, rootNames, _configOverrides);
    ...
}
public SerializationConfig(BaseSettings base, SubtypeResolver str, SimpleMixInResolver mixins, RootNameLookup rootNames,
        ConfigOverrides configOverrides)
{
    super(base, str, mixins, rootNames, configOverrides);
    _serFeatures = collectFeatureDefaults(SerializationFeature.class);
    _filterProvider = null;
    _defaultPrettyPrinter = DEFAULT_PRETTY_PRINTER;
    _generatorFeatures = 0;
    _generatorFeaturesToChange = 0;
    _formatWriteFeatures = 0;
    _formatWriteFeaturesToChange = 0;
}

默认情况下,将调用DateSerializer的_timestamp 方法:

/**
 * For efficiency, we will serialize Dates as longs, instead of
 * potentially more readable Strings.
 */
@JacksonStdImpl
@SuppressWarnings("serial")
public class DateSerializer extends DateTimeSerializerBase<Date> {
    ...

    @Override
    protected long _timestamp(Date value) {
        return (value == null) ? 0L : value.getTime();
    }

    @Override
    public void serialize(Date value, JsonGenerator g, SerializerProvider provider) throws IOException {
        if (_asTimestamp(provider)) {
            g.writeNumber(_timestamp(value));
            return;
        }
        _serializeAsString(value, g, provider);
    }
}

DateTimeSerializerBase的_asTimestamp方法:

protected boolean _asTimestamp(SerializerProvider serializers)
{
    if (_useTimestamp != null) {
        return _useTimestamp.booleanValue();
    }
    if (_customFormat == null) {
        if (serializers != null) {
            return serializers.isEnabled(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        }
        // 12-Jun-2014, tatu: Is it legal not to have provider? Was NPE:ing earlier so leave a check
        throw new IllegalArgumentException("Null SerializerProvider passed for "+handledType().getName());
    }
    return false;
}

待续....

Spring boot与Jackson ObjectMapper

上一篇:H5+混合移动app应用开发——坑我太甚


下一篇:java.io.IOException: There appears to be a gap in the edit log. We expected txid ***, but got txid