聊一聊JSON解析之树模型思想

时间:2020-6-30 作者:admin


JSON解析之树模型思想

JSON解析

常见解析器

  1. Jsonlib(官方Json接口实现的实现类)
  2. Gson(谷歌)
  3. fastjson(阿里巴巴)
  4. jackson(Spring MVC 框架内置的解析器)

基本使用

  1. 添加jackson的相关依赖/导入jackson的相关jar包
  2. 创建Jackson核心对象 ObjectMapper
  3. 调用ObjectMapper的相关方法进行转换

无论是序列化还是反序列化,Jackson都提供了三种方式

  1. JSON <–> Java Object (对象绑定,也是我们用得最多的)
  2. JSON <–> JsonNode Tree(类似于XML的DOM树)
  3. JSON <–> Json Stream (这是一个低层次的api,很强大,但是比较繁琐)

如何解析JSON

尽管有很多种拆分JSON并解析的方法,但是可以归纳成3种:

  1. 迭代:对事件流(Jackson称之为Token流)的迭代
  2. 数据绑定:将Json数据绑定到对象
  3. 遍历树:构建一个树结构并使用合适的方法遍历它

接下来将用到的方法简述

  1. public JsonNode readTree(String var1)
    Jackson提供一个树节点被称为”JsonNode”,我将其称之为该json树的根节点对象
  2. public JsonNode get(String var1)
    根据键名,返回JsonNode节点对象
  3. public String asText()
    有值返回值,无值返回空字符串

实战

问题描述

[{
  "object": [{
    "content": 103,
    "name": "编码",
    "code": "code"
  }, {
    "content": "经理层(部门)",
    "name": "名称",
    "code": "name"
  }, {
    "content": "0001A110000000002D15",
    "name": "上级部门",
    "code": "pk_fatherorg"
  }, {
    "content": 10,
    "name": "上级业务单元编码",
    "code": "fatherorg_code"
  }, {
    "content": "中南控股集团有限公司",
    "name": "上级业务单元名称",
    "code": "fatherorg_name"
  }, {
    "content": "中南集团",
    "name": "所属集团名称",
    "code": "group_name"
  }, {
    "content": "1001B210000000EQ6D5U",
    "name": "组织主键",
    "code": "pk_org"
  }, {
    "content": 0,
    "name": "删除标志",
    "code": "dr"
  }, {
    "content": "2020-01-02 11:26:25",
    "name": "时间戳",
    "code": "ts"
  }, {
    "content": "Y",
    "name": "是否生效状态",
    "code": "iseffect"
  }, {
    "content": "控股",
    "name": "所属产业",
    "code": "corp"
  }]
}, {
  "object": [{
    "content": 102,
    "name": "编码",
    "code": "code"
  }, {
    "content": "董事会(部门)",
    "name": "名称",
    "code": "name"
  }, {
    "content": "0001A110000000002D15",
    "name": "上级部门",
    "code": "pk_fatherorg"
  }, {
    "content": 10,
    "name": "上级业务单元编码",
    "code": "fatherorg_code"
  }, {
    "content": "中南控股集团有限公司",
    "name": "上级业务单元名称",
    "code": "fatherorg_name"
  }, {
    "content": "中南集团",
    "name": "所属集团名称",
    "code": "group_name"
  }, {
    "content": "1001B210000000EQ6D61",
    "name": "组织主键",
    "code": "pk_org"
  }, {
    "content": 0,
    "name": "删除标志",
    "code": "dr"
  }, {
    "content": "2018-11-21 09:06:00",
    "name": "时间戳",
    "code": "ts"
  }, {
    "content": "Y",
    "name": "是否生效状态",
    "code": "iseffect"
  }, {
    "content": "控股",
    "name": "所属产业",
    "code": "corp"
  }]
}]

解析需求

聊一聊JSON解析之树模型思想

解析结果

[{
    "code":103,"name":"经理层(部门)",
    "pk_fatherorg":"0001A110000000002D15",
    "fatherorg_code":10,"fatherorg_name":"中南控股集团有限公司",
    "group_name":"中南集团","pk_org":"1001B210000000EQ6D5U",
    "dr":0,
    "ts":"2020-01-02 11:26:25","iseffect":"Y","corp":"控股"
},
{
    "code":102,
    "name":"董事会(部门)",
    "pk_fatherorg":"0001A110000000002D15",
    "fatherorg_code":10,
    "fatherorg_name":"中南控股集团有限公司",
    "group_name":"中南集团",
    "pk_org":"1001B210000000EQ6D61",
    "dr":0,
    "ts":"2018-11-21 09:06:00",
    "iseffect":"Y","corp":"控股"
}]

代码实现

创建实体类

/**
 * @author Mitchell
 * @Description
 * @create 2020-04-04 19:21
 */
public class CustomObject {
    private Integer code;
    private String name;
    private String pk_fatherorg;
    private Integer fatherorg_code;
    private String fatherorg_name;
    private String group_name;
    private String pk_org;
    private Integer dr;
    private String ts;
    private String iseffect;
    private String corp;

	........(省略getter setter toString() 构造方法)
	

核心解析代码

/**
 * @author Mitchell
 * @Description 使用Jackson工具解析JSON的优化。使用DOM文档对象模型的思想。
 * @create 2020-04-04 19:34
 */
public class JacksonOptimizing {
    /**
     * 对象容器,存解析结果
     */
    private static List<CustomObject> customObjectList = new ArrayList<>();

    public static void main(String[] args) throws IOException {
        String json = "[{\n" +
                "  \"object\": [{\n" +
                "    \"content\": 103,\n" +
                "    \"name\": \"编码\",\n" +
                "    \"code\": \"code\"\n" +
                "  }, {\n" +
                "    \"content\": \"经理层(部门)\",\n" +
                "    \"name\": \"名称\",\n" +
                "    \"code\": \"name\"\n" +
                "  }, {\n" +
                "    \"content\": \"0001A110000000002D15\",\n" +
                "    \"name\": \"上级部门\",\n" +
                "    \"code\": \"pk_fatherorg\"\n" +
                "  }, {\n" +
                "    \"content\": 10,\n" +
                "    \"name\": \"上级业务单元编码\",\n" +
                "    \"code\": \"fatherorg_code\"\n" +
                "  }, {\n" +
                "    \"content\": \"中南控股集团有限公司\",\n" +
                "    \"name\": \"上级业务单元名称\",\n" +
                "    \"code\": \"fatherorg_name\"\n" +
                "  }, {\n" +
                "    \"content\": \"中南集团\",\n" +
                "    \"name\": \"所属集团名称\",\n" +
                "    \"code\": \"group_name\"\n" +
                "  }, {\n" +
                "    \"content\": \"1001B210000000EQ6D5U\",\n" +
                "    \"name\": \"组织主键\",\n" +
                "    \"code\": \"pk_org\"\n" +
                "  }, {\n" +
                "    \"content\": 0,\n" +
                "    \"name\": \"删除标志\",\n" +
                "    \"code\": \"dr\"\n" +
                "  }, {\n" +
                "    \"content\": \"2020-01-02 11:26:25\",\n" +
                "    \"name\": \"时间戳\",\n" +
                "    \"code\": \"ts\"\n" +
                "  }, {\n" +
                "    \"content\": \"Y\",\n" +
                "    \"name\": \"是否生效状态\",\n" +
                "    \"code\": \"iseffect\"\n" +
                "  }, {\n" +
                "    \"content\": \"控股\",\n" +
                "    \"name\": \"所属产业\",\n" +
                "    \"code\": \"corp\"\n" +
                "  }]\n" +
                "}, {\n" +
                "  \"object\": [{\n" +
                "    \"content\": 102,\n" +
                "    \"name\": \"编码\",\n" +
                "    \"code\": \"code\"\n" +
                "  }, {\n" +
                "    \"content\": \"董事会(部门)\",\n" +
                "    \"name\": \"名称\",\n" +
                "    \"code\": \"name\"\n" +
                "  }, {\n" +
                "    \"content\": \"0001A110000000002D15\",\n" +
                "    \"name\": \"上级部门\",\n" +
                "    \"code\": \"pk_fatherorg\"\n" +
                "  }, {\n" +
                "    \"content\": 10,\n" +
                "    \"name\": \"上级业务单元编码\",\n" +
                "    \"code\": \"fatherorg_code\"\n" +
                "  }, {\n" +
                "    \"content\": \"中南控股集团有限公司\",\n" +
                "    \"name\": \"上级业务单元名称\",\n" +
                "    \"code\": \"fatherorg_name\"\n" +
                "  }, {\n" +
                "    \"content\": \"中南集团\",\n" +
                "    \"name\": \"所属集团名称\",\n" +
                "    \"code\": \"group_name\"\n" +
                "  }, {\n" +
                "    \"content\": \"1001B210000000EQ6D61\",\n" +
                "    \"name\": \"组织主键\",\n" +
                "    \"code\": \"pk_org\"\n" +
                "  }, {\n" +
                "    \"content\": 0,\n" +
                "    \"name\": \"删除标志\",\n" +
                "    \"code\": \"dr\"\n" +
                "  }, {\n" +
                "    \"content\": \"2018-11-21 09:06:00\",\n" +
                "    \"name\": \"时间戳\",\n" +
                "    \"code\": \"ts\"\n" +
                "  }, {\n" +
                "    \"content\": \"Y\",\n" +
                "    \"name\": \"是否生效状态\",\n" +
                "    \"code\": \"iseffect\"\n" +
                "  }, {\n" +
                "    \"content\": \"控股\",\n" +
                "    \"name\": \"所属产业\",\n" +
                "    \"code\": \"corp\"\n" +
                "  }]\n" +
                "}]\n";
        //实体类
        CustomObject customObject = null;
        //调用解析方法
        parse(customObjectList, customObject, json);
        //解析完成
        customObjectList.forEach(System.out::println);
    }

    /**
     * JSON解析方法
     *
     * @param customObject
     * @param customObject
     * @param json
     */
    private static void parse(List<CustomObject> customObjectList, CustomObject customObject, String json) throws IOException {
        //创建Jackson的核心对象 ObjectMapper
        ObjectMapper objectMapper = new ObjectMapper();
        //读取JSON树结构,获得根节点对象
        JsonNode jsonNodeRoot = objectMapper.readTree(json);
        //遍历根节点下的直接子节点
        for (int i = 0; i < jsonNodeRoot.size(); i++) {
            customObject = new CustomObject();
            //获得键名为object的节点
            JsonNode jsonNodeObject = jsonNodeRoot.get(i).get("object");
            for (int j = 0; j < jsonNodeObject.size(); j++) {
                String code = jsonNodeObject.get(j).get("code").asText();
                switch (code) {
                    case "code":
                        customObject.setCode(Integer.parseInt(getPropertyValue(jsonNodeObject, j)));
                        break;
                    case "name":
                        customObject.setName(getPropertyValue(jsonNodeObject, j));
                        break;
                    case "pk_fatherorg":
                        customObject.setPk_fatherorg(getPropertyValue(jsonNodeObject, j));
                        break;
                    case "fatherorg_code":
                        customObject.setFatherorg_code(Integer.parseInt(getPropertyValue(jsonNodeObject, j)));
                        break;
                    case "fatherorg_name":
                        customObject.setFatherorg_name(getPropertyValue(jsonNodeObject, j));
                        break;
                    case "group_name":
                        customObject.setGroup_name(getPropertyValue(jsonNodeObject, j));
                    case "pk_org":
                        customObject.setPk_org(getPropertyValue(jsonNodeObject, j));
                        break;
                    case "dr":
                        customObject.setDr(Integer.parseInt(getPropertyValue(jsonNodeObject, j)));
                        break;
                    case "ts":
                        customObject.setTs(getPropertyValue(jsonNodeObject, j));
                        break;
                    case "iseffect":
                        customObject.setIseffect(getPropertyValue(jsonNodeObject, j));
                        break;
                    case "corp":
                        customObject.setCorp(getPropertyValue(jsonNodeObject, j));
                        break;
                }
            }
            //将对象添加入集合中
            customObjectList.add(customObject);
        }
    }

    /**
     * 通过节点对象和遍历次数来获得,键名为“content”的值
     *
     * @param jsonNodeObject
     * @param j
     * @return String
     */
    private static String getPropertyValue(JsonNode jsonNodeObject, int j) {
        return jsonNodeObject.get(j).get("content").asText();
    }
}

运行结果

聊一聊JSON解析之树模型思想

总结

  1. Databinding(数据绑定)是最常用的json处理方式,生成json时,创建相关的java对象,并根据json内容结构把java对象组装起来。
    解析时,直接把json映射到相关的java对象,遍历java对象即可取值。
  2. TreeModel处理json,是以树型结构来生成和解析json,生成json时,根据json内容结构,创建不同类型的节点对象,组装这些节点生成json。解析json时,不需要绑定json到java bean,根据json结构,找到所需的节点,使用path或get方法查找内容。
声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:87074139@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。