【Jackson】使用学习

Jackson学习

文档:http://tutorials.jenkov.com/java-json/index.html

https://github.com/FasterXML/jackson/wiki

 转载:https://www.cnblogs.com/yangchongxing/p/9153150.html

目录

=================================================================================

0、配置

1、序列化和反序列化,字段名称相同

2、序列化和反序列化,字段名称不同

3、反序列化列表对象List<CompanyLoopPicture>

4、Unrecognized field、反序列化时json中包含bean对象中没有的字段,也就是json中的字段比bean中的多

5、序列化自定义过滤器 - 普通对象

6、序列化自定义过滤器 - List中的对象字段

7、NULL、DEFAULT、EMPTY不参与序列化

8、指定属性命名策略

9、设置序列化包含、即属性显示与否

10、日期格式化

=================================================================================

0、配置

spring:
  # jackson 配置
  jackson:
    # 日期格式化
    date-format: yyyy-MM-dd HH:mm:ss
    # 时区
    time-zone: GMT+8
    # 序列化
    serialization:
      # 格式化输出,true格式化了有利于人看
      indent-output: false
      # 忽略无法转换的对象
      fail-on-empty-beans: false
    # 反序列化
    deserialization:
      # 允许对象忽略json中不存在的属性
      fail-on-ignored-properties: false
    # 设置空如何序列化
    default-property-inclusion: non_null
    # 转化
    parser:
      # 允许出现特殊字符和转义符
      allow-unquoted-control-chars: true
      # 允许出现单引号
      allow-single-quotes: true
# 日期格式化
spring.jackson.date-format = yyyy-MM-dd HH:mm:ss
# 时区
spring.jackson.time-zone = GMT+8
# 序列化
# 格式化输出,true格式化了有利于人看
spring.jackson.serialization.indent-output = false
# 忽略无法转换的对象
spring.jackson.serialization.fail-on-empty-beans = false
# 反序列化
# 允许对象忽略json中不存在的属性
spring.jackson.deserialization.fail-on-ignored-properties = false
# 设置空如何序列化
spring.jackson.default-property-inclusion = non_null
# 允许出现特殊字符和转义符
spring.jackson.parser.allow-unquoted-control-chars = true
# 允许出现单引号
spring.jackson.parser.allow-single-quotes = true

Java 工具对象

static ObjectMapper objectMapper = new ObjectMapper();
static {
    // 如果json中有实体类中不存在的字段不报错
    objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
    objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
}

1、序列化和反序列化,字段名称相同

package com.qq.weixin.mp.result;

import com.fasterxml.jackson.databind.ObjectMapper;

public class AccessTokenResult {
    private String accessToken;
    private long expiresIn;
    public String getAccessToken() {
        return accessToken;
    }
    public void setAccessToken(String accessToken) {
        this.accessToken = accessToken;
    }
    public long getExpiresIn() {
        return expiresIn;
    }
    public void setExpiresIn(long expiresIn) {
        this.expiresIn = expiresIn;
    }
    @Override
    public String toString() {
        return "AccessTokenResult [accessToken=" + accessToken + ", expiresIn=" + expiresIn + "]";
    }
    public static void main(String[] args) {
        AccessTokenResult bean = new AccessTokenResult();
        bean.setAccessToken("2r5fx9eiyapFxEGgHq");
        bean.setExpiresIn(7200);
        try {
            ObjectMapper mapper = new ObjectMapper();
            String json = mapper.writeValueAsString(bean);//序列化
            System.out.println(json);
            AccessTokenResult object = mapper.readValue(json, AccessTokenResult.class);//反序列化
            System.out.println(object);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

结果

{"accessToken":"2r5fx9eiyapFxEGgHq","expiresIn":7200}
AccessTokenResult [accessToken=2r5fx9eiyapFxEGgHq, expiresIn=7200]

2、序列化和反序列化,字段名称不同

@JsonProperty(value="access_token") 也可以指定在属性字段上,这样就不用分别指定 get 和 set 方法了

package com.qq.weixin.mp.result;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;

public class AccessTokenResult {
    private String accessToken;
    private long expiresIn;
    @JsonProperty(value="access_token")
    public String getAccessToken() {
        return accessToken;
    }
    @JsonProperty(value="access_token")
    public void setAccessToken(String accessToken) {
        this.accessToken = accessToken;
    }
    
    @JsonProperty(value="expires_in")
    public long getExpiresIn() {
        return expiresIn;
    }
    @JsonProperty(value="expires_in")
    public void setExpiresIn(long expiresIn) {
        this.expiresIn = expiresIn;
    }
    @Override
    public String toString() {
        return "AccessTokenResult [accessToken=" + accessToken + ", expiresIn=" + expiresIn + "]";
    }
    public static void main(String[] args) {
        AccessTokenResult bean = new AccessTokenResult();
        bean.setAccessToken("2r5fx9eiyapFxEGgHq");
        bean.setExpiresIn(7200);
        try {
            ObjectMapper mapper = new ObjectMapper();
            String json = mapper.writeValueAsString(bean);//序列化
            System.out.println(json);
            AccessTokenResult object = mapper.readValue(json, AccessTokenResult.class);//反序列化
            System.out.println(object);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

结果

{"access_token":"2r5fx9eiyapFxEGgHq","expires_in":7200}
AccessTokenResult [accessToken=2r5fx9eiyapFxEGgHq, expiresIn=7200]

@JsonProperty注解,作用在get方法将属性名序列化为指定的名称,作用在set方法将指定名称反序列化到属性

 3、反序列化列表对象List<CompanyLoopPicture>

public static void main(String[] args) {
    try {
        List<CompanyLoopPicture> list = new ArrayList<CompanyLoopPicture>();
        CompanyLoopPicture clp = new CompanyLoopPicture();
        clp.setId(1);
        clp.setCompanyId(100);
        clp.setTitle("google");
        clp.setPicture("/upload/images/1.jpg");
        clp.setLink("http://www.google.com");
        clp.setFlag("modify");
        list.add(clp);
        
        clp = new CompanyLoopPicture();
        clp.setId(2);
        clp.setCompanyId(200);
        clp.setTitle("intel");
        clp.setPicture("/upload/images/2.jpg");
        clp.setLink("http://www.intel.com");
        clp.setFlag("delete");
        list.add(clp);
        
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(list);
        System.out.println(json);
        
        JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, CompanyLoopPicture.class);
        List<CompanyLoopPicture> newList = mapper.readValue(json, javaType);
或者
List<CompanyLoopPicture> newList = mapper.readValue(json, new TypeReference<List<CompanyLoopPicture>>(){}); System.out.println(newList); }
catch (Exception e) { e.printStackTrace(); } }

使用public <T> T readValue(String content, JavaType valueType)

JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, CompanyLoopPicture.class); 指定集合类型以及泛型类型

 4、Unrecognized field、反序列化时json中包含bean对象中没有的字段,也就是json中的字段比bean中的多

ObjectMapper mapper = new ObjectMapper();

mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

或者 mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

并且给Bean类的顶部追加@JsonIgnoreProperties(ignoreUnknown=true),忽略未知就可解决。

@JsonIgnore注解用来忽略某些字段,可以用在Field或者Getter方法上,用在Setter方法时,和Filed效果一样。这个注解只能用在POJO存在的字段要忽略的情况。
@JsonIgnoreProperties(ignoreUnknown = true),将这个注解写在类上之后,就会忽略类中不存在的字段,。这个注解还可以指定要忽略的字段。使用方法如下:
@JsonIgnoreProperties({ "internalId", "secretKey" })指定的字段不会被序列化和反序列化。

5、序列化自定义过滤器 - 普通对象

package com.yuanxingyuan.weixin.test;
/**
 * 测试用对象
 * @author 杨崇兴
 *
 */
public class Person {
    private String name;
    private String postAddress;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getPostAddress() {
        return postAddress;
    }
    public void setPostAddress(String postAddress) {
        this.postAddress = postAddress;
    }
}

定义过滤器接口

package com.yuanxingyuan.weixin.test;

import com.fasterxml.jackson.annotation.JsonFilter;

@JsonFilter("MyJacksonFilter")
public interface MyJacksonFilter {

}

实现

package com.yuanxingyuan.weixin.test;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.databind.ser.PropertyWriter;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.yuanxingyuan.weixin.param.AddNewsArticleParam;
import com.yuanxingyuan.weixin.param.AddNewsParam;
import com.yuanxingyuan.weixin.util.JacksonUtil;

public class MaterialServiceTest {
    public static void main(String[] args) throws JsonProcessingException {
        Person person = new Person();
        person.setName("杨崇兴");
        person.setPostAddress("陕西省 西安市");
        person.setAge(18);
        // 方式一:定义Filter
        SimpleBeanPropertyFilter filter = SimpleBeanPropertyFilter.serializeAllExcept("age");
        // 方式二:或重写 SimpleBeanPropertyFilter的 serializeAsField 方法
        SimpleBeanPropertyFilter filter2 = new SimpleBeanPropertyFilter() {
            @Override
            public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer) throws Exception {
                if (!writer.getName().equals("age")) {
                    writer.serializeAsField(pojo, jgen, provider);
                }
            }
        };
        // 定义Provider
        FilterProvider filterProvider = new SimpleFilterProvider().addFilter("MyJacksonFilter", filter);// 或者用filter2
        // 数据绑定
        ObjectMapper mapper = new ObjectMapper();
        mapper.addMixIn(Person.class, MyJacksonFilter.class);
        mapper.setFilterProvider(filterProvider);
        String json = mapper.writeValueAsString(person);
        System.out.println(json);
    }
}

结果

{"name":"杨崇兴","postAddress":"陕西省 西安市"}

mapper.addMixIn(Person.class, MyJacksonFilter.class);很关键

addMixIn 方法签名如下:
public ObjectMapper addMixIn(Class<?> target, Class<?> mixinSource);
addMixIn 方法的作用是用 mixinSource 接口或类的注解会重写 target 或 target 的子类型的注解

6、序列化自定义过滤器 - List中的对象字段

测试Bean

package com.yuanxingyuan.weixin.param;

import java.util.List;

public class AddNewsParam {
    /**
     * 文章
     */
    private List<AddNewsArticleParam> articles;

    public List<AddNewsArticleParam> getArticles() {
        return articles;
    }

    public void setArticles(List<AddNewsArticleParam> articles) {
        this.articles = articles;
    }
}



package com.yuanxingyuan.weixin.param;

public class AddNewsArticleParam {
    /**
     * 标题
     */
    private String title;
    /**
     * 图文消息的封面图片素材id(必须是永久mediaID)
     */
    private String thumbMediaId;
    /**
     * 作者
     * 【非必须】
     */
    private String author;
    /**
     * 图文消息的摘要,仅有单图文消息才有摘要,多图文此处为空。如果本字段为没有填写,则默认抓取正文前64个字。
     * 【非必须】
     */
    private String digest;
    /**
     * 是否显示封面,0为false,即不显示,1为true,即显示
     */
    private boolean showCoverPic;
    /**
     * 图文消息的具体内容,支持HTML标签,必须少于2万字符,小于1M,
     * 且此处会去除JS,涉及图片url必须来源 "上传图文消息内的图片获取URL"接口获取。
     * 外部图片url将被过滤。
     */
    private String content;
    /**
     * 图文消息的原文地址,即点击“阅读原文”后的URL
     */
    private String contentSourceUrl;
    
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getThumbMediaId() {
        return thumbMediaId;
    }
    public void setThumbMediaId(String thumbMediaId) {
        this.thumbMediaId = thumbMediaId;
    }
    public String getAuthor() {
        return author;
    }
    public void setAuthor(String author) {
        this.author = author;
    }
    public String getDigest() {
        return digest;
    }
    public void setDigest(String digest) {
        this.digest = digest;
    }
    public boolean getShowCoverPic() {
        return showCoverPic;
    }
    public void setShowCoverPic(boolean showCoverPic) {
        this.showCoverPic = showCoverPic;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    public String getContentSourceUrl() {
        return contentSourceUrl;
    }
    public void setContentSourceUrl(String contentSourceUrl) {
        this.contentSourceUrl = contentSourceUrl;
    }
}

过滤对象AddNewsArticleParam中的非必需字段,author,digest

package com.yuanxingyuan.weixin.test;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.databind.ser.PropertyWriter;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.yuanxingyuan.weixin.param.AddNewsArticleParam;
import com.yuanxingyuan.weixin.param.AddNewsParam;
import com.yuanxingyuan.weixin.util.JacksonUtil;

public class MaterialServiceTest {
    public static void main(String[] args) throws JsonProcessingException {
        AddNewsArticleParam article = new AddNewsArticleParam();
        article.setTitle("Title");
        article.setThumbMediaId("MediaId");
        article.setShowCoverPic(true);
        article.setContent("content");
        article.setContentSourceUrl("url");
        article.setAuthor("Author");
        article.setDigest("Digest");
        List<AddNewsArticleParam> articles = new ArrayList<AddNewsArticleParam>();
        articles.add(article);
        AddNewsParam news = new AddNewsParam();
        news.setArticles(articles);
        
        String json1 = JacksonUtil.toJson(AddNewsArticleParam.class, news, new String[]{"author","digest"});
        System.out.println(json1);
}
    /**
     * 序列化(自定义过滤器)
     * @param clazz
     * @param value
     * @param filterFields
     * @return
     */
    public static String toJson(Class<?> clazz, Object value, String[] filterFields) {
        try {
            SimpleBeanPropertyFilter filter = SimpleBeanPropertyFilter.serializeAllExcept(filterFields);
            FilterProvider filterProvider = new SimpleFilterProvider().addFilter("MyJacksonFilter", filter);
            ObjectMapper mapper = new ObjectMapper();
            mapper.addMixIn(clazz, MyJacksonFilter.class);
            mapper.setFilterProvider(filterProvider);
            return mapper.writeValueAsString(value);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

 特别注意:addMixIn中的class是List中对象的class

7、NULL、DEFAULT、EMPTY不参与序列化

方式一、使用@JsonInclude注解

放在属性上仅对该属性起作用,放在类上对整个类的属性起作用包含继承来的属性

@JsonInclude(Include.NON_NULL) ,属性为NULL时不参与序列化

方式二、使用代码

ObjectMapper mapper = new ObjectMapper();

mapper.setSerializationInclusion(Include.NON_NULL); 

可设置的值:

Include.Include.ALWAYS (默认)属性都序列化
Include.NON_DEFAULT 属性为默认值不序列化
Include.NON_EMPTY 属性为空或者为NULL不序列化
Include.NON_NULL 属性为NULL不序列化

8、指定属性命名策略

Company c = new Company();
c.setName("apple");
c.setPostalCode("100000");
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(PropertyNamingStrategy.UPPER_CAMEL_CASE);
try {
    String json = mapper.writeValueAsString(c);// 序列化
    System.out.println(json);
    Company company = mapper.readValue(json, Company.class);//反序列化
    System.out.println(company.toString());
} catch (Exception e) {
    e.printStackTrace();
}

PropertyNamingStrategy 的常量值

命名策略 序列化结果
SNAKE_CASE {"name":"apple","postal_code":"100000"}
UPPER_CAMEL_CASE {"Name":"apple","PostalCode":"100000"}
LOWER_CAMEL_CASE {"name":"apple","postalCode":"100000"}
LOWER_CASE "name":"apple","postalcode":"100000"}
KEBAB_CASE {"name":"apple","postal-code":"100000"}

9、设置序列化包含、即属性显示与否

name 设置为空 postalCode 设置为null

Company c = new Company();
c.setName("");
c.setPostalCode(null);
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
try {
    String json = mapper.writeValueAsString(c);// 序列化
    System.out.println(json);
    Company company = mapper.readValue(json, Company.class);//反序列化
    System.out.println(company.toString());
} catch (Exception e) {
    e.printStackTrace();
}

JsonInclude.Include

序列化包含 序列化结果
ALWAYS {"name":"","postalCode":null}   不管是空还是null都包含在序列化结果中
NON_NULL {"name":""} 不包含值为null的属性
NON_DEFAULT {}
NON_EMPTY {}  不包含值为空或null的属性
NON_ABSENT {"name":""}  不包含值为null或absent like Java 8 `Optional`, or {link java.utl.concurrent.atomic.AtomicReference}的属性
USE_DEFAULTS {"name":"","postalCode":null}
CUSTOM 被 JsonInclude#valueFilter 和 JsonInclude#contentFilter 指定的

10、日期格式化

import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;

@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
@TableField("time_")
private String time;
原文地址:https://www.cnblogs.com/yangchongxing/p/9153150.html