• jackson学习之三:常用API操作


    欢迎访问我的GitHub

    https://github.com/zq2599/blog_demos

    内容:所有原创文章分类汇总及配套源码,涉及Java、Docker、Kubernetes、DevOPS等;

    系列文章汇总

    源码下载

    1. 如果您不想编码,可以在GitHub下载所有源码,地址和链接信息如下表所示(https://github.com/zq2599/blog_demos):
    名称 链接 备注
    项目主页 https://github.com/zq2599/blog_demos 该项目在GitHub上的主页
    git仓库地址(https) https://github.com/zq2599/blog_demos.git 该项目源码的仓库地址,https协议
    git仓库地址(ssh) git@github.com:zq2599/blog_demos.git 该项目源码的仓库地址,ssh协议
    1. 这个git项目中有多个文件夹,本章的应用在jacksondemo文件夹下,如下图红框所示:

    在这里插入图片描述

    本篇概览

    本文是《jackson学习》系列的第三篇,前面咱们学习了jackson的低阶API,知道了底层原理,本篇开始学习平时最常用的基本功能,涉及内容如下:

    1. 体验最常用的操作,内容如下图所示:

    在这里插入图片描述

    1. 介绍常用的可配置属性,以便按需要来设置;
    2. 接下来进入快速浏览的环节,咱们一起先把各个API过一遍;

    单个对象序列化

    先看常用的序列化API:

    1. 对象转字符串:
    String jsonStr = mapper.writeValueAsString(twitterEntry);
    
    1. 对象转文件:
    mapper.writeValue(new File("twitter.json"), twitterEntry);
    
    1. 对象转byte数组:
    byte[] array = mapper.writeValueAsBytes(twitterEntry);
    

    单个对象反序列化

    1. 字符串转对象:
    TwitterEntry tFromStr = mapper.readValue(objectJsonStr, TwitterEntry.class);
    
    1. 文件转对象:
    TwitterEntry tFromFile = mapper.readValue(new File("twitter.json"), TwitterEntry.class);
    
    1. byte数组转对象:
    TwitterEntry tFromBytes = mapper.readValue(array, TwitterEntry.class);
    
    1. 字符串网络地址转对象:
    String testJsonDataUrl = "https://raw.githubusercontent.com/zq2599/blog_demos/master/files/twitteer_message.json";
    
    TwitterEntry tFromUrl = mapper.readValue(new URL(testJsonDataUrl), TwitterEntry.class);
    

    集合序列化

    1. HashMap转字符串:
    String mapJsonStr = mapper.writeValueAsString(map);
    

    集合反序列化

    1. 字符串转HashMap:
    Map<String, Object> mapFromStr = mapper.readValue(mapJsonStr, new TypeReference<Map<String, Object>>() {});
    

    JsonNode

    1. 如果您不想使用XXX.class来做反序列化,也能使用JsonNode来操作:
    JsonNode jsonNode = mapper.readTree(mapJsonStr);
    String name = jsonNode.get("name").asText();
    int age = jsonNode.get("age").asInt();
    String city = jsonNode.get("addr").get("city").asText();
    String street = jsonNode.get("addr").get("street").asText();
    

    时间字段格式化

    1. 对于Date字段,默认的反序列化是时间戳,可以修改配置:
    mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"));
    dateMapStr = mapper.writeValueAsString(dateMap);
    

    JSON数组的反序列化

    假设jsonArrayStr是个json数组格式的字符串:

    1. JSON数组转对象数组:
    TwitterEntry[] twitterEntryArray = mapper.readValue(jsonArrayStr, TwitterEntry[].class);
    
    1. JSON数组转对象集合(ArrayList):
    List<TwitterEntry> twitterEntryList = mapper.readValue(jsonArrayStr, new TypeReference<List<TwitterEntry>>() {});
    

    完整代码

    1. 上述所有常用API用法的完整代码如下:
    package com.bolingcavalry.jacksondemo.databind;
    
    import com.bolingcavalry.jacksondemo.beans.TwitterEntry;
    import com.fasterxml.jackson.core.type.TypeReference;
    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import java.io.File;
    import java.net.URL;
    import java.text.SimpleDateFormat;
    import java.util.*;
    
    public class SimpleDemo {
    
        private static final Logger logger = LoggerFactory.getLogger(SimpleDemo.class);
    
        public static void main(String[] args) throws Exception {
            ObjectMapper mapper = new ObjectMapper();
    
            logger.info("以下是序列化操作");
    
            // 对象 -> 字符串
            TwitterEntry twitterEntry = new TwitterEntry();
            twitterEntry.setId(123456L);
            twitterEntry.setFromUserId(101);
            twitterEntry.setToUserId(102);
            twitterEntry.setText("this is a message for serializer test");
            twitterEntry.setLanguageCode("zh");
    
            String jsonStr = mapper.writeValueAsString(twitterEntry);
            logger.info("序列化的字符串:{}", jsonStr);
    
            // 对象 -> 文件
            mapper.writeValue(new File("twitter.json"), twitterEntry);
    
            // 对象 -> byte数组
            byte[] array = mapper.writeValueAsBytes(twitterEntry);
    
            logger.info("
    
    以下是反序列化操作");
    
            // 字符串 -> 对象
            String objectJsonStr = "{
    " +
                    "  "id":1125687077,
    " +
                    "  "text":"@stroughtonsmith You need to add a \"Favourites\" tab to TC/iPhone. Like what TwitterFon did. I can't WAIT for your Twitter App!! :) Any ETA?",
    " +
                    "  "fromUserId":855523, 
    " +
                    "  "toUserId":815309,
    " +
                    "  "languageCode":"en"
    " +
                    "}";
    
    
            TwitterEntry tFromStr = mapper.readValue(objectJsonStr, TwitterEntry.class);
            logger.info("从字符串反序列化的对象:{}", tFromStr);
    
            // 文件 -> 对象
            TwitterEntry tFromFile = mapper.readValue(new File("twitter.json"), TwitterEntry.class);
            logger.info("从文件反序列化的对象:{}", tFromStr);
    
            // byte数组 -> 对象
            TwitterEntry tFromBytes = mapper.readValue(array, TwitterEntry.class);
            logger.info("从byte数组反序列化的对象:{}", tFromBytes);
    
            // 字符串网络地址 -> 对象
            String testJsonDataUrl = "https://raw.githubusercontent.com/zq2599/blog_demos/master/files/twitteer_message.json";
    
            TwitterEntry tFromUrl = mapper.readValue(new URL(testJsonDataUrl), TwitterEntry.class);
            logger.info("从网络地址反序列化的对象:{}", tFromUrl);
    
    
            logger.info("
    
    以下是集合序列化操作");
    
            Map<String, Object> map = new HashMap<>();
            map.put("name", "tom");
            map.put("age", 11);
    
            Map<String, String> addr = new HashMap<>();
            addr.put("city","深圳");
            addr.put("street", "粤海");
    
            map.put("addr", addr);
    
            String mapJsonStr = mapper.writeValueAsString(map);
            logger.info("HashMap序列化的字符串:{}", mapJsonStr);
    
            logger.info("
    
    以下是集合反序列化操作");
            Map<String, Object> mapFromStr = mapper.readValue(mapJsonStr, new TypeReference<Map<String, Object>>() {});
            logger.info("从字符串反序列化的HashMap对象:{}", mapFromStr);
    
            // JsonNode类型操作
            JsonNode jsonNode = mapper.readTree(mapJsonStr);
            String name = jsonNode.get("name").asText();
            int age = jsonNode.get("age").asInt();
            String city = jsonNode.get("addr").get("city").asText();
            String street = jsonNode.get("addr").get("street").asText();
    
            logger.info("用JsonNode对象和API反序列化得到的数:name[{}]、age[{}]、city[{}]、street[{}]", name, age, city, street);
    
            // 时间类型格式
    
            Map<String, Object> dateMap = new HashMap<>();
            dateMap.put("today", new Date());
    
            String dateMapStr = mapper.writeValueAsString(dateMap);
            logger.info("默认的时间序列化:{}", dateMapStr);
    
            // 设置时间格式
            mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"));
            dateMapStr = mapper.writeValueAsString(dateMap);
            logger.info("自定义的时间序列化:{}", dateMapStr);
    
            System.out.println(objectJsonStr);
    
            // json数组
            String jsonArrayStr = "[{
    " +
                    "  "id":1,
    " +
                    "  "text":"text1",
    " +
                    "  "fromUserId":11, 
    " +
                    "  "toUserId":111,
    " +
                    "  "languageCode":"en"
    " +
                    "},
    " +
                    "{
    " +
                    "  "id":2,
    " +
                    "  "text":"text2",
    " +
                    "  "fromUserId":22, 
    " +
                    "  "toUserId":222,
    " +
                    "  "languageCode":"zh"
    " +
                    "},
    " +
                    "{
    " +
                    "  "id":3,
    " +
                    "  "text":"text3",
    " +
                    "  "fromUserId":33, 
    " +
                    "  "toUserId":333,
    " +
                    "  "languageCode":"en"
    " +
                    "}]";
    
            // json数组 -> 对象数组
            TwitterEntry[] twitterEntryArray = mapper.readValue(jsonArrayStr, TwitterEntry[].class);
            logger.info("json数组反序列化成对象数组:{}", Arrays.toString(twitterEntryArray));
    
            // json数组 -> 对象集合
            List<TwitterEntry> twitterEntryList = mapper.readValue(jsonArrayStr, new TypeReference<List<TwitterEntry>>() {});
            logger.info("json数组反序列化成对象集合:{}", twitterEntryList);
        }
    }
    
    1. 执行结果如下:
    C:jdkinjava.exe -javaagent:C:sofwareJetBrainsIntelliJIDEAlibidea_rt.jar=64570:C:sofwareJetBrainsIntelliJIDEAin -Dfile.encoding=UTF-8 -classpath C:jdkjrelibcharsets.jar;C:jdkjrelibdeploy.jar;C:jdkjrelibextaccess-bridge-64.jar;C:jdkjrelibextcldrdata.jar;C:jdkjrelibextdnsns.jar;C:jdkjrelibextjaccess.jar;C:jdkjrelibextjfxrt.jar;C:jdkjrelibextlocaledata.jar;C:jdkjrelibext
    ashorn.jar;C:jdkjrelibextsunec.jar;C:jdkjrelibextsunjce_provider.jar;C:jdkjrelibextsunmscapi.jar;C:jdkjrelibextsunpkcs11.jar;C:jdkjrelibextzipfs.jar;C:jdkjrelibjavaws.jar;C:jdkjrelibjce.jar;C:jdkjrelibjfr.jar;C:jdkjrelibjfxswt.jar;C:jdkjrelibjsse.jar;C:jdkjrelibmanagement-agent.jar;C:jdkjrelibplugin.jar;C:jdkjrelib
    esources.jar;C:jdkjrelib
    t.jar;D:githublog_demosjacksondemodatabind	argetclasses;C:Users12167.m2
    epositorycomfasterxmljacksoncorejackson-databind2.11.0jackson-databind-2.11.0.jar;C:Users12167.m2
    epositorycomfasterxmljacksoncorejackson-annotations2.11.0jackson-annotations-2.11.0.jar;C:Users12167.m2
    epositorycomfasterxmljacksoncorejackson-core2.11.0jackson-core-2.11.0.jar;C:Users12167.m2
    epositoryorgslf4jslf4j-log4j121.7.25slf4j-log4j12-1.7.25.jar;C:Users12167.m2
    epositoryorgslf4jslf4j-api1.7.25slf4j-api-1.7.25.jar;C:Users12167.m2
    epositorylog4jlog4j1.2.17log4j-1.2.17.jar;C:Users12167.m2
    epositorycommons-iocommons-io2.7commons-io-2.7.jar;C:Users12167.m2
    epositoryorgapachecommonscommons-lang33.10commons-lang3-3.10.jar;D:githublog_demosjacksondemoeans	argetclasses com.bolingcavalry.jacksondemo.databind.SimpleDemo
    2020-08-28 07:53:01 INFO  SimpleDemo:27 - 以下是序列化操作
    2020-08-28 07:53:01 INFO  SimpleDemo:38 - 序列化的字符串:{"id":123456,"text":"this is a message for serializer test","fromUserId":101,"toUserId":102,"languageCode":"zh"}
    2020-08-28 07:53:01 INFO  SimpleDemo:47 - 
    
    以下是反序列化操作
    2020-08-28 07:53:01 INFO  SimpleDemo:60 - 从字符串反序列化的对象:[Tweet, id: 1125687077, text='@stroughtonsmith You need to add a "Favourites" tab to TC/iPhone. Like what TwitterFon did. I can't WAIT for your Twitter App!! :) Any ETA?', from: 855523, to: 815309, lang: en]
    2020-08-28 07:53:01 INFO  SimpleDemo:64 - 从文件反序列化的对象:[Tweet, id: 1125687077, text='@stroughtonsmith You need to add a "Favourites" tab to TC/iPhone. Like what TwitterFon did. I can't WAIT for your Twitter App!! :) Any ETA?', from: 855523, to: 815309, lang: en]
    2020-08-28 07:53:01 INFO  SimpleDemo:68 - 从byte数组反序列化的对象:[Tweet, id: 123456, text='this is a message for serializer test', from: 101, to: 102, lang: zh]
    2020-08-28 07:53:04 INFO  SimpleDemo:74 - 从网络地址反序列化的对象:[Tweet, id: 112233445566, text='this is a message from zq2599's github', from: 201, to: 202, lang: en]
    2020-08-28 07:53:04 INFO  SimpleDemo:77 - 
    
    以下是集合序列化操作
    2020-08-28 07:53:04 INFO  SimpleDemo:90 - HashMap序列化的字符串:{"name":"tom","addr":{"city":"深圳","street":"粤海"},"age":11}
    2020-08-28 07:53:04 INFO  SimpleDemo:92 - 
    
    以下是集合反序列化操作
    2020-08-28 07:53:04 INFO  SimpleDemo:94 - 从字符串反序列化的HashMap对象:{name=tom, addr={city=深圳, street=粤海}, age=11}
    2020-08-28 07:53:04 INFO  SimpleDemo:103 - 用JsonNode对象和API反序列化得到的数:name[tom]、age[11]、city[深圳]、street[粤海]
    2020-08-28 07:53:04 INFO  SimpleDemo:111 - 默认的时间序列化:{"today":1598572384838}
    2020-08-28 07:53:04 INFO  SimpleDemo:116 - 自定义的时间序列化:{"today":"2020-08-28 07:53:04"}
    {
      "id":1125687077,
      "text":"@stroughtonsmith You need to add a "Favourites" tab to TC/iPhone. Like what TwitterFon did. I can't WAIT for your Twitter App!! :) Any ETA?",
      "fromUserId":855523, 
      "toUserId":815309,
      "languageCode":"en"
    }
    2020-08-28 07:53:04 INFO  SimpleDemo:145 - json数组反序列化成对象数组:[[Tweet, id: 1, text='text1', from: 11, to: 111, lang: en], [Tweet, id: 2, text='text2', from: 22, to: 222, lang: zh], [Tweet, id: 3, text='text3', from: 33, to: 333, lang: en]]
    2020-08-28 07:53:04 INFO  SimpleDemo:149 - json数组反序列化成对象集合:[[Tweet, id: 1, text='text1', from: 11, to: 111, lang: en], [Tweet, id: 2, text='text2', from: 22, to: 222, lang: zh], [Tweet, id: 3, text='text3', from: 33, to: 333, lang: en]]
    
    Process finished with exit code 0
    
    1. 还会产生名为twitter.json的文件,内容如下:
    {"id":123456,"text":"this is a message for serializer test","fromUserId":101,"toUserId":102,"languageCode":"zh"}
    

    常用配置

    下面是平时可能用到的自定义配置项目:

    1. 序列化结果格式化:
    mapper.enable(SerializationFeature.INDENT_OUTPUT);
    
    1. 空对象不要抛出异常:
    mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
    
    1. Date、Calendar等序列化为时间格式的字符串(如果不执行以下设置,就会序列化成时间戳格式):
    mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    
    1. 反序列化时,遇到未知属性不要抛出异常:
    mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    
    1. 反序列化时,空字符串对于的实例属性为null:
    mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
    
    1. 允许C和C++样式注释:
    mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
    
    1. 允许字段名没有引号(可以进一步减小json体积):
    mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
    
    1. 允许单引号:
    mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
    

    特殊配置:在json对象最外层再包裹一层

    1. 最后要说的是个特殊配置,先来看看正常情况一个普通的序列化结果:
    {
      "id" : 1,
      "text" : "aabbcc",
      "fromUserId" : 456,
      "toUserId" : 0,
      "languageCode" : "zh"
    }
    
    1. 接下来咱们做两件事,首先,是给上述json对应的实例类添加一个注解,如下图红框:

    在这里插入图片描述
    3. 其次,执行以下配置:

    mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
    
    1. 然后再次执行TwitterEntry实例的序列化,得到的结果如下,可见和之前的序列化结果相比,之前的整个json都变成了一个value,此value对应的key就是注解JsonRootName的value属性:
    {
      "aaa" : {
        "id" : 1,
        "text" : "aabbcc",
        "fromUserId" : 456,
        "toUserId" : 0,
        "languageCode" : "zh"
      }
    }
    
    • 至此,开发中常用的API和配置都已经介绍完成,希望能给您带来一些参考,接下来的章节,咱们一起去了解另一个常用操作:jackson注解

    你不孤单,欣宸原创一路相伴

    1. Java系列
    2. Spring系列
    3. Docker系列
    4. kubernetes系列
    5. 数据库+中间件系列
    6. DevOps系列

    欢迎关注公众号:程序员欣宸

    微信搜索「程序员欣宸」,我是欣宸,期待与您一同畅游Java世界...
    https://github.com/zq2599/blog_demos

  • 相关阅读:
    [转载]项目风险管理七种武器之引言
    [转载]基于TFS实践敏捷-Scrum模式运用
    [转载]基于TFS实践敏捷-工作项跟踪
    [转载]TFS入门指南
    SVN — subclipse操作指引
    Java 中 方法名或类名 变更 同时 更新 所有引用的 类名或方法名 的解决方案
    Java import javax.servlet 出错
    java 中 SVN 设置所有文件及子目录 needs-lock, svn 提交时自动设置 needs-lock, 及版本不一致问题
    vmware 传输(vmdb)错误-32:pipe:read failed 解决方法
    Web.xml配置详解
  • 原文地址:https://www.cnblogs.com/bolingcavalry/p/14337888.html
Copyright © 2020-2023  润新知