Jackson使用ObjectMapper

Java的Json组件主要有Alibaba的FastJson 和 FasterXML的Jackson,比较常用的是Jackson

一、Jackson

Jackson的核心类是ObjectMapper,通过ObjectMapper可以序列化和反序列化Json。

使用Jackson把Java对象转Json:

常用的有:

1、writeValue(参数一,参数二);

参数一:

(1) File:将obj对象转换为JSON字符串,并保存到指定的文件中

(2) Writer:将obj对象转换为JSON字符串,并将json数据填充到字符输出流中(通常可以使用respon的getWrite()方法,获取该类)

(3) OutputStream:将obj对象转换为JSON字符串,并将json数据填充到字节输出流中

参数二:
  要转换为JSON的对象 
2、writeValueAsString(obj):将对象转为json字符串

3、可以转换普通POJO对象,List对象,Map对象

Jackson转Json到Java对象:

通常使用:
readValue(String json,Class cla)

Jackson相关注解:

@JsonIgnore:实体类的属性加上此注解就会在转成json时忽略该属性

@JsonFormat: 可以将属性值在转成json时格式化

2、注解使用

2.1、@JsonProperty注解使用

@JsonProperty注解类似于sql里字段的别名,用于序列化,使用注解字段属性,替代原字段属性

@JsonProperty(“userName”)
private String name;
序列化结果为:在序列化的json串中,userName替代了name

@JsonIgnore注解是在序列化时忽略该字段

  @JsonIgnore
    @JsonProperty("userName")
    private String name;
    @JsonProperty("userAge")
    private Integer age;

序列化结果为:{“userAge”:20}

{“userAge”:20}
2.3、@JsonIgnoreProperties注解使用

**2.3.1、**序列化@JsonIgnoreProperties与@JsonIgnore类似,用于类上,注解使用的是字段别名

复制代码

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;

@JsonIgnoreProperties(value={"name","userAge"})
public class Person {
    @JsonIgnore
    @JsonProperty("userName")
    private String name;
    @JsonProperty("userAge")
    private Integer age;
    @JsonProperty("userHeight")
    private Integer height;

    public Person(String name, Integer age, Integer height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }
}

复制代码

ObjectMapper mapper = new ObjectMapper();
Person person = new Person("jackson",20,175);
System.out.println(mapper.writeValueAsString(person));

运行结果为:{“userHeight”:175}

2.3.2、@JsonIgnoreProperties(ignoreUnknown = true)用于忽略字段不匹配情况,相当于mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

备注:反序列化需要有无参构造器

ObjectMapper mapper = new ObjectMapper();
Person person = new Person("jackson",20,175);
System.out.println(mapper.writeValueAsString(person));
//mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
System.out.println(mapper.readValue("{\"sheight\":172}", Person.class).getHeight());

2.4、@JsonTypeName @JsonTypeInfo

@JsonTypeName(value = "user")
@JsonTypeInfo(include = JsonTypeInfo.As.WRAPPER_OBJECT, use = JsonTypeInfo.Id.NAME)

在序列化是增加一层

序列化结果为:{“user”:{“height”:175}}

{“user”:{“height”:175}}

2.5、@JsonRootName注解

2.4组合在序列化上等于类上注解@JsonRootName(“user”) 和 mapper.enable(SerializationFeature.WRAP_ROOT_VALUE),反序列化无用;

2.6、@JsonFormat注解格式化日期格式

@JsonFormat(pattern=“yyyy-MM-dd HH:mm:ss:SSS”,timezone=“GMT+8”)
private Date date;

2.7、@JsonAnyGetter注解
@JsonAnyGetter注解主要用在序列化:
1.方法是非静态,没有参数的,方法名随意
2.方法返回值必须是Map类型
3.在一个实体类中仅仅用在一个方法上
4.序列化的时候json字段的key就是返回Map的key,value就是Map的value

//@JsonAnyGetter
public Map getMap(){
    return map;
}

序列化结果为:{“height”:175,“map”:{“1”:“1”,“key”:“value”},“date”:“2019-05-29 10:37:55:759”}

取消注释后序列化结果为:{“height”:175,“date”:“2019-05-29 10:39:14:685”,“1”:“1”,“key”:“value”}

2.8、@JsonAnySetter注解
@JsonAnySetter注解主要作用于反序列化上:
1.用在非静态方法上,注解的方法必须有两个参数,第一个是json字段中的key,第二个是value,方法名随意
2.反序列化的时候将对应不上的字段全部放到Map里面

JavaType

list反序列化为LinkedHashMap如果要转换为原来对象类型

如果为Map类型 mapper.getTypeFactory().constructParametricType(Map.class,String.class,Student.class);// 第二个参数是Map的key,第三个参数是Map的value
如果为List类型 personList = mapper.readValue(mapper.writeValueAsString(personList),mapper.getTypeFactory().constructParametricType(List.class,Person.class));

TypeReference

TypeReference比javaType模式更加方便,代码也更加简洁

mapper.readValue(json, new TypeReference(){});

序列化自定义

可以使用序列化(SerializationFeature)与反序列化(DeserializationFeature)自定义规则。

需要自定义Jackson序列化和反序列化有两种方式,一种是全局定义,一种是非全局定义。先来看看全局定义。全局定义的步骤如下,以定义一个localDateTime的序列化和反序列化为例:

一、创建一个序列化类

创建一个序列化类然后继承JsonSerializer,重写serialize序列化方法。其中第一个参数localDateTime为JsonSerializer的泛型,表示的是被序列化的类型的值,第二个参数jsonGenerator表示的是用于输出生成的Json内容,第三个参数暂时没明白什么应用场景。重写方法一般是将想要序列化的字符串传入 jsonGenerator.writeString。

public final class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
    public static final LocalDateTimeSerializer INSTANCE = new LocalDateTimeSerializer();

    public LocalDateTimeSerializer() {
    }
    @Override
    public void serialize(LocalDateTime localDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
        jsonGenerator.writeString(DateUtil.format(localDateTime, DateUtil.DateTimeFormatEnum.DATE_TIME_FORMAT_4));
    }
}

二、创建一个反序列化类
创建一个类继承JsonDeserializer,重写deserialize反序列化方法。参数jsonParser用于读取json内容的解析,deserializationContext可用于访问此有关反序列化的上下文(暂时也不知道怎么用),返回值则是JsonDeserializer的泛型对象,表示要反序列化的对象。一般用法是通过jsonParser.getText().trim()获取该字段json字符串,然后将该字符串转换为对象返回。

public final class LocalTimeDeserializer extends JsonDeserializer<LocalTime> {
    public static final LocalTimeDeserializer INSTANCE = new LocalTimeDeserializer();

    public LocalTimeDeserializer() {
    }
    @Override
    public LocalTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
        String text = jsonParser.getText().trim();
        return LocalTime.parse(text, DateUtil.DATE_TIME_FORMATTER_6);
    }
}

三、将两个类注册进入jackson核心对象objectMapper

public ObjectMapper objectMapper(){
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //不注释,会导致swagger报错
        //objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        //关闭日期序列化为时间戳的功能
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        //关闭序列化的时候没有为属性找到getter方法,报错
        objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        //关闭反序列化的时候,没有找到属性的setter报错
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        //序列化的时候序列对象的所有属性
        objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
        //反序列化的时候如果多了其他属性,不抛出异常
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        //如果是空对象的时候,不抛异常
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(LocalDateTime.class, LocalDateTimeSerializer.INSTANCE);
        simpleModule.addKeyDeserializer(LocalDateTime.class, LocalDateTimeKeyDeserializer.INSTANCE);
        objectMapper.registerModule(simpleModule);
        return objectMapper;
    }

配置处理LocalDate LocalTime LocalDateTime字段的序列化和反序列格式

    /** 默认日期时间格式 */
    public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    /** 默认日期格式 */
    public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    /** 默认时间格式 */
    public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
 public void method1() throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));
        javaTimeModule.addSerializer(LocalDate.class,new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
        javaTimeModule.addSerializer(LocalTime.class,new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
        javaTimeModule.addDeserializer(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));
        javaTimeModule.addDeserializer(LocalDate.class,new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
        javaTimeModule.addDeserializer(LocalTime.class,new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
        objectMapper.registerModule(javaTimeModule).registerModule(new ParameterNamesModule());
         PersonExtWithOriginalRequestDTO personExtWithOriginalRequestDTO = objectMapper.readValue("",PersonExtWithOriginalRequestDTO.class);
   }

注:可以在spring java config中统一配置ObjectMapper bean

四、总结
以上,通过objectMapper的配置,完成了全局序列化、反序列化的配置,如果不需要全局则通过@jsonserialize或 @JsonDeserialize指定使用的序列化、反序列化类。

你可能感兴趣的:(Jackson使用ObjectMapper)