千家信息网

Spring Boot中Jackson应用详解

发表于:2024-09-22 作者:千家信息网编辑
千家信息网最后更新 2024年09月22日,Spring Boot支持与三种JSON mapping库集成:Gson、Jackson和JSON-B。Jackson是首选和默认的。Jackson是spring-boot-starter-json依
千家信息网最后更新 2024年09月22日Spring Boot中Jackson应用详解

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。

    org.springframework.boot    spring-boot-starter-web

Jackson

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 parse(String content, Class valueType) throws IOException {        return mapper.readValue(content, valueType);    }}

编写一简单POJO测试类:

import java.util.Date;public class Hero {     private String name;    private Date birthday;    public static void main(String[] args) throws Exception {        System.out.println(JsonUtil.generate(new Hero("Jason", new Date())));    }    public Hero() {    }    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,日期将转换为Timestamp。可查看如下源码:

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

默认情况下,Date类型序列化将调用DateSerializer的_timestamp 方法:

/** * For efficiency, we will serialize Dates as longs, instead of * potentially more readable Strings. */@JacksonStdImpl@SuppressWarnings("serial")public class DateSerializer extends DateTimeSerializerBase {    ...    @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;}

禁用WRITE_DATES_AS_TIMESTAMPS
若要将日期序列化为字符串,可禁用SerializationFeature.WRITE_DATES_AS_TIMESTAMPS:

mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

这时序列化将调用StdDateFormat的format()方法,使用ISO-8601兼容格式"yyyy-MM-dd'T'HH:mm:ss.SSSZ",输出内容如下:

{"name":"Jason","birthday":"2018-10-31T03:07:34.485+0000"}

StdDateFormat反序列化支持ISO-8601兼容格式和RFC-1123("EEE, dd MMM yyyy HH:mm:ss zzz")格式。

@JsonFormat
使用@JsonFormat注解,代替全局设置,是一种更灵活的方法:

@JsonFormat(shape = JsonFormat.Shape.STRING)private Date birthday;

还可以定义pattern:

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")private Date birthday;

当自定义pattern后,将创建新的SimpleDateFormat实例来序列化日期,参见DateTimeSerializerBase的createContextual()方法:

public JsonSerializer createContextual(SerializerProvider serializers, BeanProperty property) throws JsonMappingException{  ...  if (format.hasPattern()) {      final Locale loc = format.hasLocale() ? format.getLocale() : serializers.getLocale();      SimpleDateFormat df = new SimpleDateFormat(format.getPattern(), loc);      TimeZone tz = format.hasTimeZone() ? format.getTimeZone() : serializers.getTimeZone();      df.setTimeZone(tz);      return withFormat(Boolean.FALSE, df);  }  ...}

常用注解

不过多解释各注解的作用,请看输出结果。
示例1

import com.fasterxml.jackson.annotation.JsonAlias;import com.fasterxml.jackson.annotation.JsonIgnoreProperties;import com.fasterxml.jackson.annotation.JsonInclude;import com.fasterxml.jackson.annotation.JsonPropertyOrder;@JsonPropertyOrder({"firstName", "lastName"})@JsonIgnoreProperties({"id"})@JsonInclude(JsonInclude.Include.NON_NULL)public class Hero {    private Integer id;    // define one or more alternative names for a property during deserialization.    @JsonAlias({"fName", "f_name"})    private String firstName;    private String lastName;    public static void main(String[] args) throws Exception {        System.out.println(JsonUtil.generate(new Hero(1, "Jason", "Sun")));        System.out.println(JsonUtil.generate(new Hero(1, "Jason", null)));        System.out.println(JsonUtil.parse("{\"fName\":\"Jason\",\"lastName\":\"Sun\"}", Hero.class).getFirstName());    }    public Hero() {    }    public Hero(Integer id, String firstName, String lastName) {        this.id = id;        this.firstName = firstName;        this.lastName = lastName;    }    // getter and setter}       

输出结果:

{"firstName":"Jason","lastName":"Sun"}{"firstName":"Jason"}Jason

示例2

import com.fasterxml.jackson.annotation.JsonIgnore;import com.fasterxml.jackson.annotation.JsonIgnoreType;import com.fasterxml.jackson.annotation.JsonProperty;public class Hero {    @JsonIgnore    private Integer id;    private String nickname;    private Name name;    @JsonProperty("mail")    private String email;    @JsonIgnoreType    public static class Name {        private String firstName;        private String lastName;        public Name(String firstName, String lastName) {            this.firstName = firstName;            this.lastName = lastName;        }        // getter and setter    }    public static void main(String[] args) throws Exception {        System.out.println(JsonUtil.generate(new Hero(1, "chuanchuan", new Name("Jason", "Sun"), "jason@163.com")));    }    public Hero() {    }    public Hero(Integer id, String nickname, Name name, String email) {        this.id = id;        this.nickname = nickname;        this.name = name;        this.email = email;    }    // getter and setter}       

输出结果:

{"nickname":"chuanchuan","mail":"jason@163.com"}

示例3
使用@JsonValue控制整个类序列化的结果,一个类中最多只能含有一个@JsonValue。

import com.fasterxml.jackson.annotation.JsonValue;public class HeroWithValue {    private Integer id;    @JsonValue    private String name;    private String email;    public static void main(String[] args) throws Exception {        System.out.println(JsonUtil.generate(new HeroWithValue(1, "Jason", "jason@163.com")));    }    public HeroWithValue(Integer id, String name, String email) {        this.id = id;        this.name = name;        this.email = email;    }    // getter and setter}

输出结果:

"Jason"

示例4

public class Views {    public static class Public {    }    public static class Internal extends Public {    }}
import com.fasterxml.jackson.annotation.JsonView;import com.fasterxml.jackson.databind.ObjectMapper;public class HeroWithView {    @JsonView(Views.Public.class)    private int id;    @JsonView(Views.Public.class)    private String name;    @JsonView(Views.Internal.class)    private String email;    public static void main(String[] args) throws Exception {        HeroWithView hero = new HeroWithView(1, "Jason", "jason@163.com");        String publicResult = new ObjectMapper().writerWithView(Views.Public.class).writeValueAsString(hero);        String internalResult = new ObjectMapper().writerWithView(Views.Internal.class).writeValueAsString(hero);        System.out.println(publicResult);        System.out.println(internalResult);    }    public HeroWithView(int id, String name, String email) {        this.id = id;        this.name = name;        this.email = email;    }}

输出结果:

{"id":1,"name":"Jason"}{"id":1,"name":"Jason","email":"jason@163.com"}

示例5

import com.fasterxml.jackson.annotation.JsonRootName;import com.fasterxml.jackson.annotation.JsonUnwrapped;import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.SerializationFeature;@JsonRootName(value = "hero")public class UnwrappedHero {    private int id;    @JsonUnwrapped    private Name name;    public static void main(String[] args) throws Exception {        ObjectMapper mapper = new ObjectMapper();        mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);        System.out.println(mapper.writeValueAsString(new UnwrappedHero(1, new Name("Jason", "Sun"))));    }    public UnwrappedHero(int id, Name name) {        this.id = id;        this.name = name;    }    public static class Name {        private String firstName;        private String lastName;        public Name(String firstName, String lastName) {            this.firstName = firstName;            this.lastName = lastName;        }        // getter and setter    }    // getter and setter}

示例6

import com.fasterxml.jackson.annotation.JsonSubTypes;import com.fasterxml.jackson.annotation.JsonTypeInfo;import com.fasterxml.jackson.annotation.JsonTypeName;public class Zoo {    private Animal animal;    public Zoo(Animal animal) {        this.animal = animal;    }    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")    @JsonSubTypes({            @JsonSubTypes.Type(value = Dog.class, name = "dog"),            @JsonSubTypes.Type(value = Cat.class, name = "cat")    })    public static class Animal {        private String name;        public Animal(String name) {            this.name = name;        }        public String getName() {            return name;        }        public void setName(String name) {            this.name = name;        }    }    @JsonTypeName("dog")    public static class Dog extends Animal {        private double barkVolume;        public Dog(String name) {            super(name);        }        public double getBarkVolume() {            return barkVolume;        }        public void setBarkVolume(double barkVolume) {            this.barkVolume = barkVolume;        }    }    @JsonTypeName("cat")    public static class Cat extends Animal {        private boolean likesCream;        private int lives;        public Cat(String name) {            super(name);        }        public boolean isLikesCream() {            return likesCream;        }        public void setLikesCream(boolean likesCream) {            this.likesCream = likesCream;        }        public int getLives() {            return lives;        }        public void setLives(int lives) {            this.lives = lives;        }    }    public static void main(String[] args) throws Exception {        System.out.println(JsonUtil.generate(new Zoo(new Dog("lacy"))));        System.out.println(JsonUtil.generate(new Zoo(new Cat("tom"))));    }    public Animal getAnimal() {        return animal;    }    public void setAnimal(Animal animal) {        this.animal = animal;    }}

输出结果:

{"animal":{"type":"dog","name":"lacy","barkVolume":0.0}}{"animal":{"type":"cat","name":"tom","likesCream":false,"lives":0}}

示例7
双向关联时如未做处理,会发生错误:com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError),可组合使用@JsonManagedReference和@JsonBackReference。

public class Hero {    private Integer id;    private String name;    @JsonManagedReference    private List races = new ArrayList<>();    public static void main(String[] args) throws Exception {        Hero hero = new Hero(1, "jason");        Race race = new Race(1, "marathon", 42.195f);        hero.addRace(race);        System.out.println(JsonUtil.generate(hero));        System.out.println(JsonUtil.generate(race));    }    public Hero(Integer id, String name) {        this.id = id;        this.name = name;    }    public void addRace(Race race) {        races.add(race);        race.setHero(this);    }    // getter and setter}
import com.fasterxml.jackson.annotation.JsonBackReference;public class Race {    private Integer id;    private String type;    private Float distance;    @JsonBackReference    private Hero hero;    public Race(Integer id, String type, Float distance) {        this.id = id;        this.type = type;        this.distance = distance;    }    // getter and setter}

输出结果:

{"id":1,"name":"jason","races":[{"id":1,"type":"marathon","distance":42.195}]}{"id":1,"type":"marathon","distance":42.195}

示例8
双向关联的另一种解决方案,使用@JsonIdentityInfo。

import com.fasterxml.jackson.annotation.JsonIdentityInfo;import com.fasterxml.jackson.annotation.ObjectIdGenerators;import java.util.ArrayList;import java.util.List;@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")public class Hero {    private Integer id;    private String name;    private List races = new ArrayList<>();    public static void main(String[] args) throws Exception {        Hero hero = new Hero(1, "jason");        Race race = new Race(1, "marathon", 42.195f);        hero.addRace(race);        System.out.println(JsonUtil.generate(hero));        System.out.println(JsonUtil.generate(race));    }    public Hero(Integer id, String name) {        this.id = id;        this.name = name;    }    public void addRace(Race race) {        races.add(race);        race.setHero(this);    }    // getter and setter}
import com.fasterxml.jackson.annotation.JsonIdentityInfo;import com.fasterxml.jackson.annotation.ObjectIdGenerators;@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")public class Race {    private Integer id;    private String type;    private Float distance;    private Hero hero;    public Race(Integer id, String type, Float distance) {        this.id = id;        this.type = type;        this.distance = distance;    }    // getter and setter}

输出结果:

{"id":1,"name":"jason","races":[{"id":1,"type":"marathon","distance":42.195,"hero":1}]}{"id":1,"type":"marathon","distance":42.195,"hero":{"id":1,"name":"jason","races":[1]}}

示例9
上例,如果要Race序列化结果仅含有hero id,可以组合使用@JsonIdentityInfo和@JsonIdentityReference。

import com.fasterxml.jackson.annotation.JsonIdentityInfo;import com.fasterxml.jackson.annotation.ObjectIdGenerators;import java.util.ArrayList;import java.util.List;@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", resolver = HeroIdResolver.class)public class Hero {    private Integer id;    private String name;    private List races = new ArrayList<>();    public static void main(String[] args) throws Exception {        Hero hero = new Hero(1, "jason");        Race race = new Race(1, "marathon", 42.195f);        hero.addRace(race);        System.out.println(JsonUtil.generate(hero));        System.out.println(JsonUtil.generate(race));    }    public Hero(Integer id) {        this.id = id;    }    public Hero(Integer id, String name) {        this.id = id;        this.name = name;    }    public void addRace(Race race) {        races.add(race);        race.setHero(this);    }    // getter and setter}
import com.fasterxml.jackson.annotation.JsonIdentityInfo;import com.fasterxml.jackson.annotation.ObjectIdGenerators;@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")public class Race {    private Integer id;    private String type;    private Float distance;    @JsonIdentityReference(alwaysAsId = true)    @JsonProperty("heroId")    private Hero hero;    public Race(Integer id, String type, Float distance) {        this.id = id;        this.type = type;        this.distance = distance;    }    // getter and setter}

为了支持反序列化,需要自定义ObjectIdResolver:

import com.fasterxml.jackson.annotation.ObjectIdGenerator;import com.fasterxml.jackson.annotation.ObjectIdResolver;public class HeroIdResolver implements ObjectIdResolver {    @Override    public void bindItem(ObjectIdGenerator.IdKey id, Object pojo) {    }    @Override    public Object resolveId(ObjectIdGenerator.IdKey id) {        return new Hero((Integer) id.key);    }    @Override    public ObjectIdResolver newForDeserialization(Object context) {        return new HeroIdResolver();    }    @Override    public boolean canUseFor(ObjectIdResolver resolverType) {        return resolverType.getClass() == getClass();    }}

输出结果:

{"id":1,"name":"jason","races":[{"id":1,"type":"marathon","distance":42.195,"heroId":1}]}{"id":1,"type":"marathon","distance":42.195,"heroId":1}

示例10
自定义Annotation,将多个Annotation组合起来。

import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;import com.fasterxml.jackson.annotation.JsonInclude;import com.fasterxml.jackson.annotation.JsonPropertyOrder;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;@Retention(RetentionPolicy.RUNTIME)@JacksonAnnotationsInside@JsonInclude(JsonInclude.Include.NON_NULL)@JsonPropertyOrder({"name", "id", "dateCreated"})public @interface CustomAnnotation {}
import java.util.Date;@CustomAnnotationpublic class HeroWithCustomAnnotation {    private Integer id;    private String name;    private Date dateCreated;    public static void main(String[] args) throws Exception {        System.out.println(JsonUtil.generate(new HeroWithCustomAnnotation(1, "Jason", null)));    }    public HeroWithCustomAnnotation(Integer id, String name, Date dateCreated) {        this.id = id;        this.name = name;        this.dateCreated = dateCreated;    }    // getter and setter}

输出结果:

{"name":"Jason","id":1}

Spring Boot与Jackson

Spring Boot使用HttpMessageConverters处理HTTP交换中的内容转换。当classpath中存在Jackson时,Jackson2ObjectMapperBuilder提供默认的Converter,源码请查看HttpMessageConverters和WebMvcConfigurationSupport:
HttpMessageConverters

private List> getDefaultConverters() {    List> converters = new ArrayList<>();    if (ClassUtils.isPresent("org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport", null)) {        converters.addAll(new WebMvcConfigurationSupport() {            public List> defaultMessageConverters() {                return super.getMessageConverters();            }        }.defaultMessageConverters());    }    else {        converters.addAll(new RestTemplate().getMessageConverters());    }    reorderXmlConvertersToEnd(converters);    return converters;}

WebMvcConfigurationSupport

protected final void addDefaultHttpMessageConverters(List> messageConverters) {    StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();    stringHttpMessageConverter.setWriteAcceptCharset(false);  // see SPR-7316    messageConverters.add(new ByteArrayHttpMessageConverter());    messageConverters.add(stringHttpMessageConverter);    messageConverters.add(new ResourceHttpMessageConverter());    messageConverters.add(new ResourceRegionHttpMessageConverter());    messageConverters.add(new SourceHttpMessageConverter<>());    messageConverters.add(new AllEncompassingFormHttpMessageConverter());    ...    if (jackson2Present) {        Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json();        if (this.applicationContext != null) {            builder.applicationContext(this.applicationContext);        }        messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build()));    }    ...}

Jackson2ObjectMapperBuilder创建ObjectMapper实例:
Jackson2ObjectMapperBuilder

public  T build() {    ObjectMapper mapper;    if (this.createXmlMapper) {        mapper = (this.defaultUseWrapper != null ?                new XmlObjectMapperInitializer().create(this.defaultUseWrapper) :                new XmlObjectMapperInitializer().create());    }    else {        mapper = (this.factory != null ? new ObjectMapper(this.factory) : new ObjectMapper());    }    configure(mapper);    return (T) mapper;}...private void customizeDefaultFeatures(ObjectMapper objectMapper) {    if (!this.features.containsKey(MapperFeature.DEFAULT_VIEW_INCLUSION)) {        configureFeature(objectMapper, MapperFeature.DEFAULT_VIEW_INCLUSION, false);    }    if (!this.features.containsKey(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) {        configureFeature(objectMapper, DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);    }}

默认禁用了MapperFeature.DEFAULT_VIEW_INCLUSION、DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES。

Auto Configurationk中默认禁用了WRITE_DATES_AS_TIMESTAMPS:
JacksonAutoConfiguration

static {    Map featureDefaults = new HashMap<>();    featureDefaults.put(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);    FEATURE_DEFAULTS = Collections.unmodifiableMap(featureDefaults);}

配置Jackson

针对ObjectMapper的六种Feature,Spring Boot都提供了相应的配置,列表如下:

Feature(Enum)Spring Boot PropertyValues
com.fasterxml.jackson.databind.DeserializationFeaturespring.jackson.deserialization.feature_nametrue, false
com.fasterxml.jackson.core.JsonGenerator.Featurespring.jackson.generator.feature_nametrue, false
com.fasterxml.jackson.databind.MapperFeaturespring.jackson.mapper.feature_nametrue, false
com.fasterxml.jackson.core.JsonParser.Featurespring.jackson.parser.feature_nametrue, false
com.fasterxml.jackson.databind.SerializationFeaturespring.jackson.serialization.feature_nametrue, false
com.fasterxml.jackson.annotation.JsonInclude.Includespring.jackson.default-property-inclusionalways, non_null, non_absent, non_default, non_empty

例如,为启用美化打印,设置spring.jackson.serialization.indent_output=true,相当于启用SerializationFeature.INDENT_OUTPUT,配置中忽略feature_name大小写。

其他的Jackson配置属性:

  • spring.jackson.date-format= # Date format string or a fully-qualified date format class name. For instance, yyyy-MM-dd HH:mm:ss.
  • spring.jackson.joda-date-time-format= # Joda date time format string. If not configured, "date-format" is used as a fallback if it is configured with a format string.
  • spring.jackson.locale= # Locale used for formatting.
  • spring.jackson.property-naming-strategy= # One of the constants on Jackson's PropertyNamingStrategy. Can also be a fully-qualified class name of a PropertyNamingStrategy subclass.
  • spring.jackson.time-zone= # Time zone used when formatting dates. For instance, "America/Los_Angeles" or "GMT+10".

其中spring.jackson.date-format默认值为com.fasterxml.jackson.databind.util.StdDateFormat。

@DateTimeFormat和@JsonFormat

在REST编程中,当提交application/json的POST/PUT请求时,JSON会通过Jackson进行转换。当提交GET请求时,如参数中包含日期,后台代码需要使用注解@DateTimeFormat:

@DateTimeFormat(pattern = "yyyy-MM-dd")private Date startDate;

两者可以同时使用:

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")@DateTimeFormat(pattern = "yyyy-MM-dd")private Date startDate;

JSON编码

@RestController@RequestMapping(value = "/api", produces = MediaType.APPLICATION_JSON_VALUE)@Api(tags = {"Hello Controller"})public class HelloController {  ...}

JSON MediaType为"application/json;charset=UTF-8",默认charset为"UTF-8"。
如果遗留代码使用了GBK编码,我们修改produces为"application/json;charset=GBK",会生效么?根据JSON规范The JavaScript Object Notation (JSON) Data Interchange Format - Character Encoding,JSON仅支持UTF-8、UTF-16、UTF-32编码。

查看源码验证一下:
AbstractJackson2HttpMessageConverter

public abstract class AbstractJackson2HttpMessageConverter extends AbstractGenericHttpMessageConverter {    @Override    protected void writeInternal(Object object, @Nullable Type type, HttpOutputMessage outputMessage)            throws IOException, HttpMessageNotWritableException {        MediaType contentType = outputMessage.getHeaders().getContentType();        JsonEncoding encoding = getJsonEncoding(contentType);        JsonGenerator generator = this.objectMapper.getFactory().createGenerator(outputMessage.getBody(), encoding);        ...    }    ...    protected JsonEncoding getJsonEncoding(@Nullable MediaType contentType) {        if (contentType != null && contentType.getCharset() != null) {            Charset charset = contentType.getCharset();            for (JsonEncoding encoding : JsonEncoding.values()) {                if (charset.name().equals(encoding.getJavaName())) {                    return encoding;                }            }        }        return JsonEncoding.UTF8;    }}

JsonEncoding

public enum JsonEncoding {    UTF8("UTF-8", false, 8), // N/A for big-endian, really        UTF16_BE("UTF-16BE", true, 16),        UTF16_LE("UTF-16LE", false, 16),        UTF32_BE("UTF-32BE", true, 32),        UTF32_LE("UTF-32LE", false, 32)                ...}

可以看到JsonEncoding仅包含UTF-8、UTF-16BE、UTF-16LE、UTF-32BE、UTF-32LE几种编码。

参考文档

Jackson Annotation Examples

0