zoukankan      html  css  js  c++  java
  • 【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;
  • 相关阅读:
    iOS中 H5的input输入框focus()无法自动拉起键盘(解决方法)
    git提交待审核代码,报错没有change-id的解决方法
    Vue proxyTable 解决开发环境的跨域问题
    JSONP原理实现及url传递参数封装
    vue(v-html)和scss的使用问题
    JS获取IOS版本号
    IOS下移除按钮原生样式 -webkit-appearance
    按键排序JavaScript对象
    input输入框限制20个字符,十个汉字
    移动端小坑:用户长按H5文字出现复制
  • 原文地址:https://www.cnblogs.com/yangchongxing/p/9153150.html
Copyright © 2011-2022 走看看