Jackson

Jackson主要包含了3个模块:jackson-core、jackson-annotations、jackson-databind。有三种方式处理Json:1、使用底层的基于Stream的方式对Json的每一个小的组成部分进行控制。2、使用Tree Model,通过JsonNode处理单个Json节点。3、使用databind模块,直接对Java对象进行序列化和反序列化。通常来说,我们在日常开发中使用的是第3种方式。本文也是介绍第3种方式的序列化和反序列化。

依赖



    com.fasterxml.jackson.core
    jackson-core


    com.fasterxml.jackson.core
    jackson-annotations


    com.fasterxml.jackson.core
    jackson-databind

下面例子中所使用的对象:

@Data
@Accessors(chain = true)
public class EmployeeVo implements Serializable {
    private Long id;
    private String name;
    private Short sex;
    private Date birthday;
    private String telephone;
    private BigDecimal salary;
    private Boolean isOfficial;
    private String hobby;

    public String getAbc() {
        return "abc方法";
    }
}

默认配置的对象序列化(ObjectMapper.writeValueAsString)

    @Test
    public void writeValueAsString() throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        EmployeeVo employeeVo = new EmployeeVo();
        employeeVo.setId(1000L)
                .setName("haha")
                .setBirthday(new Date())
                .setSalary(new BigDecimal("19865.32"))
                .setIsOfficial(true)
                .setSex(new Short("0"))
                .setTelephone("021-2546589");
        System.out.println(objectMapper.writeValueAsString(employeeVo));
    }

输出结果:

{"id":1000,"name":"haha","sex":0,"birthday":1592019533928,"telephone":"021-2546589","salary":19865.32,"isOfficial":true,"hobby":null,"abc":"abc方法"}

说明:

  1. 空值会输出null
  2. Date类型会输出时间戳
  3. 序列化依赖于getter方法,如果某个字段没有getter方法,那么该字段是不会被序列化的
  4. 通过getter的命名规约进行调用,若有getAbc()方法,没有abc属性则也会序列化输出"abc":""

默认配置的对象反序列化(ObjectMapper.readValue)

@Test
public void readValue() throws JsonProcessingException {
    String jsonStr = "{\"id\":1000,\"name\":\"haha\",\"sex\":0,\"birthday\":1592013569703,\"salary\":19865.32,"isOfficial":true}";
    ObjectMapper objectMapper = new ObjectMapper();
    EmployeeVo employeeVo = objectMapper.readValue(jsonStr, EmployeeVo.class);
    System.out.println(employeeVo);
}

输入出结果:

EmployeeVo(id=1000, name=haha, sex=0, birthday=Sat Jun 13 09:59:29 CST 2020, telephone=null, salary=19865.32, isOfficial=null, hobby=null)

说明:

  1. 时间戳可以反序列化成Date
  2. Long、String、Short、BigDecimal、Boolean类型默认都支持

常用配置


反序列化时忽略对象中不存在的json字段

假如对JSON字符串做反序列化时,JSON存在对象中没有属性,默认反序列化报错。如多了一个extra属性。

String jsonStr = "{\"id\":1000,\"name\":\"haha\",\"sex\":0,\"birthday\":1592013569703,\"salary\":19865.32,\"extra\":\"test123\"}";

报如下错误:

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "extra" (class com.zmx.model.vo.EmployeeVo), not marked as ignorable (8 known properties: "hobby", "telephone", "isOfficial", "sex", "salary", "id", "birthday", "name"])

解决办法:

  1. 在EmployeeVo中添加extra属性(不可取)
  2. objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
  1. @JsonIgnoreProperties(ignoreUnknown = true) 用于类上,对于单个对象生效,而对于JSON字符串中存在的未知字段,在反序列化时忽略。
@JsonIgnoreProperties(ignoreUnknown = true)
public class EmployeeVo implements Serializable {
}
忽略字段

在序列化和反序列化时可以选择性让某些属性忽略,不会序列化也不会反序列化。

  1. @JsonIgnore 用于字段上,表示该字段在序列化和反序列化的时候都将被忽略。
@JsonIgnore
private String hobby;
  1. @JsonIgnoreProperties 主要用于类上。下面表示sex与birthday,反序列化和序列化均忽略
@JsonIgnoreProperties(value = {"sex", "birthday"})
null值属性序列化时优化处理

默认情况下序列化时,对NULL属性出成的JSON字符串会生成:"属性名":null。通过以下设置可以设置成不输出空值属性。

  1. @JsonInclude(JsonInclude.Include.NON_NULL) 设置在类上面,对单个类生效。
    @JsonInclude(JsonInclude.Include.NON_EMPTY),表示null和集合为空, @JsonInclude(JsonInclude.Include.NON_DEFAULT),表示为赋初值的情况(null,0,0.0,空集合,false);

  2. objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 设置在objectMapper上面,对objectMapper全局生效。

Date序列化和反序列化
  1. @JsonFormat (com.fasterxml.jackson.annotation.JsonFormat) 做用在类属性上面。
@JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss",timezone = "GMT+8")
private Date birthday;
  1. 设置ObjectMapper.setDateFormat()
//去掉默认的时间戳格式
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
//设置为东八区
objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
//序列化时,日期的统一格式
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
对没有get,set方法的对象序列化和反序列化
    @Test
    public void writeValueAsString2() throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
        objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
        EmployeeVo employeeVo = new EmployeeVo();
        employeeVo.setId(1000L).setName("haha").setBirthday(new Date()).setSalary(new BigDecimal("19865.32")).setIsOfficial(true).setSex(new Short("0"));
        System.out.println(objectMapper.writeValueAsString(employeeVo));
    }

结果:

{"id":1000,"name":"haha","sex":0,"birthday":1592029403004,"telephone":null,"salary":19865.32,"isOfficial":true,"hobby":null}
自己定义解析器

自定义序列化解析器

public class BigDecimalSerializer extends JsonSerializer {
    @Override
    public void serialize(BigDecimal bigDecimal, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        DecimalFormat decimalFormat = new DecimalFormat("#,##0.00");
        jsonGenerator.writeString(decimalFormat.format(bigDecimal));

    }
}

自定义反序列化解析器

public class BigDecimalDeSerializer extends JsonDeserializer {

    @Override
    public BigDecimal deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
        DecimalFormat decimalFormat = new DecimalFormat("#,##0.00");
        Number value = BigDecimal.ZERO;
        try {
            value = decimalFormat.parse(jsonParser.getText());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return new BigDecimal(value.longValue());
    }
}
  1. 做用于局部类上面
@JsonSerialize(using = BigDecimalSerializer.class)
@JsonDeserialize(using = BigDecimalDeSerializer.class)
protected BigDecimal salary;
  1. 做用于全局
ObjectMapper objectMapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(BigDecimal.class, new BigDecimalSerializer());
        module.addDeserializer(BigDecimal.class, new BigDecimalDeSerializer());
        objectMapper.registerModule(module);
其它配置
  1. @JsonIgnoreType 标注在类上,当该类作为其他类的属性时,该属性将被忽略。
  2. @JsonProperty 可以指定某个属性和json映射的名称。例如我们有个json字符串为{“user_name”:”aaa”},而java中命名要遵循驼峰规则,则为userName,这时通过@JsonProperty 注解来指定两者的映射规则即可。这个注解也比较常用。
  3. @JsonSetter 标注于 setter 方法上,类似 @JsonProperty ,也可以解决 json 键名称和 java pojo 字段名称不匹配的问题。

常用的ObjectMapper的设置

ObjectMapper objectMapper = new ObjectMapper();
//去掉默认的时间戳格式     
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
//设置为东八区
objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
// 设置输入:禁止把POJO中值为null的字段映射到json字符串中
objectMapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
 //空值不序列化
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
//反序列化时,属性不存在的兼容处理
objectMapper.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
//序列化时,日期的统一格式
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
//序列化日期时以timestamps输出,默认true
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
//序列化枚举是以toString()来输出,默认false,即默认以name()来输出
objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING,true);
//序列化枚举是以ordinal()来输出,默认false
objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_INDEX,false);
//类为空时,不要抛异常
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
//反序列化时,遇到未知属性时是否引起结果失败
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
 //单引号处理
objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
//解析器支持解析结束符
objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);

参考于:
https://www.jianshu.com/p/af96d8a5769d
https://www.jianshu.com/p/67b6da565f81

你可能感兴趣的:(Jackson)