目录

  • 说明
  • 实例代码

说明

本文章代码出自摸石头过河写出来的,隔天再写不一定写得出来,所以发个文章记录下。

为什么写这个代码
需求要求,有一段json字符串,数据结构是图下这样:

{"id": "1","string": "sb","double": "33","long": "2","boolean": "true","domain": {"id": "1","name": "大白","org": {"code": "1"},"jd": [{"j": "false","d": "4"}, {"j": "true","d": "6"}]},"orgs": [{"code": "bb","id": "true","org": {"code": "1"},"sb": [{"s": "1"}, {"b": "true"}]}, {"code": "cc","id": "false","org": {"code": "1"},"sb": [{"s": "2"}, {"b": "false"}]}]
}

可以得知,所有属性都是string类型,又得知有个Attr类,里面放着json属性对应的类型,要求我们如果json里面有属性和Attr类里面名称对应的上,就要把string转换相对应的类型。

以上可能有点绕,举个栗子:图上有个id的属性,它的值是字符串的1,Attr类里面id对应的值是integer,所以最后的结果要是integer类型。

由于json数据结构不可知,只能穷举+递归针对处理:
1、基本数据类型
2、object类型
3、array类型
4、object类型中有array类型
5、array类型中有object类型

实例代码

package com.lq.demo1.service;import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.lq.demo1.entity.Attr;
import com.lq.demo1.entity.Constants;
import lombok.extern.slf4j.Slf4j;import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;@Slf4j
public class TestService {public static void main(String[] args) throws JsonProcessingException {String json = "{\n" +"\t\"id\": \"1\",\n" +"\t\"string\": \"sb\",\n" +"\t\"double\": \"33\",\n" +"\t\"long\": \"2\",\n" +"\t\"boolean\": \"true\",\n" +"\t\"domain\": {\n" +"\t\t\"id\": \"1\",\n" +"\t\t\"name\": \"大白\",\n" +"\t\t\"org\": {\n" +"\t\t\t\"code\": \"1\"\n" +"\t\t},\n" +"\t\t\"jd\": [{\n" +"\t\t\t\"j\": \"false\",\n" +"\t\t\t\"d\": \"4\"\n" +"\t\t}, {\n" +"\t\t\t\"j\": \"true\",\n" +"\t\t\t\"d\": \"6\"\n" +"\t\t}]\n" +"\t},\n" +"\t\"orgs\": [{\n" +"\t\t\"code\": \"bb\",\n" +"\t\t\"id\": \"true\",\n" +"\t\t\"org\": {\n" +"\t\t\t\"code\": \"1\"\n" +"\t\t},\n" +"\t\t\"sb\": [{\n" +"\t\t\t\"s\": \"1\"\n" +"\t\t}, {\n" +"\t\t\t\"b\": \"true\"\n" +"\t\t}]\n" +"\t}, {\n" +"\t\t\"code\": \"cc\",\n" +"\t\t\"id\": \"false\",\n" +"\t\t\"org\": {\n" +"\t\t\t\"code\": \"1\"\n" +"\t\t},\n" +"\t\t\"sb\": [{\n" +"\t\t\t\"s\": \"2\"\n" +"\t\t}, {\n" +"\t\t\t\"b\": \"false\"\n" +"\t\t}]\n" +"\t}]\n" +"}";log.info("老:{}", json);ObjectMapper objectMapper = new ObjectMapper();ObjectNode objectNode = (ObjectNode) objectMapper.readTree(json);Attr a = Attr.builder().id(1).attributeName("id").attributeType("INTEGER").parentId(-1).build();Attr b = Attr.builder().id(2).attributeName("string").attributeType("STRING").parentId(-1).build();Attr c = Attr.builder().id(3).attributeName("double").attributeType("INTEGER").parentId(-1).build();Attr d = Attr.builder().id(4).attributeName("long").attributeType("LONG").parentId(-1).build();Attr e = Attr.builder().id(5).attributeName("boolean").attributeType("BOOLEAN").parentId(-1).build();Attr f = Attr.builder().id(6).attributeName("orgs").attributeType("JSONARRAY").parentId(-1).build();Attr g = Attr.builder().id(7).attributeName("code").attributeType("STRING").parentId(6).build();Attr h = Attr.builder().id(7).attributeName("id").attributeType("BOOLEAN").parentId(6).build();Attr l1 = Attr.builder().id(13).attributeName("org").attributeType("JSONOBJECT").parentId(6).build();Attr m1 = Attr.builder().id(14).attributeName("code").attributeType("INTEGER").parentId(13).build();Attr m11 = Attr.builder().id(15).attributeName("sb").attributeType("JSONARRAY").parentId(6).build();Attr m12 = Attr.builder().id(16).attributeName("s").attributeType("INTEGER").parentId(15).build();Attr m13 = Attr.builder().id(17).attributeName("b").attributeType("BOOLEAN").parentId(15).build();Attr i = Attr.builder().id(8).attributeName("domain").attributeType("JSONOBJECT").parentId(-1).build();Attr j = Attr.builder().id(9).attributeName("id").attributeType("INTEGER").parentId(8).build();Attr k = Attr.builder().id(10).attributeName("name").attributeType("STRING").parentId(8).build();Attr l = Attr.builder().id(11).attributeName("org").attributeType("JSONOBJECT").parentId(8).build();Attr m = Attr.builder().id(12).attributeName("code").attributeType("INTEGER").parentId(11).build();Attr m8 = Attr.builder().id(18).attributeName("jd").attributeType("JSONARRAY").parentId(8).build();Attr m9 = Attr.builder().id(19).attributeName("j").attributeType("BOOLEAN").parentId(18).build();Attr m20 = Attr.builder().id(20).attributeName("d").attributeType("INTEGER").parentId(18).build();List<Attr> attrs = new LinkedList<>();attrs.add(m8);attrs.add(m9);attrs.add(m20);attrs.add(a);attrs.add(b);attrs.add(c);attrs.add(d);attrs.add(e);attrs.add(f);attrs.add(g);attrs.add(h);attrs.add(i);attrs.add(j);attrs.add(k);attrs.add(l);attrs.add(m);attrs.add(l1);attrs.add(m1);attrs.add(m11);attrs.add(m12);attrs.add(m13);tree(attrs);log.info("树结构:{}", attrs.toString());Iterator<Map.Entry<String, JsonNode>> fields = objectNode.fields();while (fields.hasNext()) {Map.Entry<String, JsonNode> next = fields.next();String key = next.getKey();JsonNode value = next.getValue();for (Attr dto : attrs) {String attributeType = dto.getAttributeType();if (dto.getAttributeName().equals(key)) {if (!attributeType.equals(Constants.JSONARRAY) && !attributeType.equals(Constants.JSONOBJECT)) {//先把最外层的基本类型给解决掉baseNode(objectNode, key, value, attributeType);} else if (attributeType.equals(Constants.JSONOBJECT)) {//第一层的keyobjectNode(objectNode, key, key, value, attributeType, attrs);} else if (attributeType.equals(Constants.JSONARRAY)) {arraryNode(objectNode, key, key, attributeType, attrs);}}}}log.info("新:{}", objectNode.toString());}/*** @param objectNode      原始数据* @param key           原始数据中的key* @param value         key的value 需要转换类型* @param attributeType 转换的类型*/public static void baseNode(ObjectNode objectNode, String key, JsonNode value, String attributeType) {//基础类型设置值if (attributeType.equals(Constants.DOUBLE)) {objectNode.put(key, value.asDouble());} else if (attributeType.equals(Constants.INTEGER)) {objectNode.put(key, value.asInt());} else if (attributeType.equals(Constants.LONG)) {objectNode.put(key, value.asLong());} else if (attributeType.equals(Constants.BOOLEAN)) {objectNode.put(key, value.asBoolean());}}/*** @param rootObjectNode      原始数据* @param rootKey       原始数据中key* @param attrKey       追加要和attr name 拼接使用的key* @param attributeType* @param attrs*/public static void arraryNode(ObjectNode rootObjectNode, String rootKey, String attrKey, String attributeType, List<Attr> attrs) {if (attributeType.equals(Constants.JSONARRAY)) {ArrayNode jsonNodes = rootObjectNode.withArray(rootKey);for (int i = 0; i < jsonNodes.size(); i++) {JsonNode node = jsonNodes.get(i);Iterator<Map.Entry<String, JsonNode>> fields = node.fields();while (fields.hasNext()) {Map.Entry<String, JsonNode> next = fields.next();String key = next.getKey();String dkey = attrKey + "." + key;//子属性nodeJsonNode nextValue = next.getValue();for (Attr attr : attrs) {if (dkey.equals(attr.getAttributeName())) {String attributeType1 = attr.getAttributeType();if (!attributeType1.equals(Constants.JSONOBJECT) && !attributeType1.equals(Constants.JSONARRAY)) {//怎么修改值类型?ObjectNode objectNode = (ObjectNode) node;if (attributeType1.equals(Constants.DOUBLE)) {objectNode.put(key, nextValue.asInt());} else if (attributeType1.equals(Constants.INTEGER)) {objectNode.put(key, nextValue.asInt());} else if (attributeType1.equals(Constants.LONG)) {objectNode.put(key, nextValue.asLong());} else if (attributeType1.equals(Constants.BOOLEAN)) {objectNode.put(key, nextValue.asBoolean());} else if (attributeType1.equals(Constants.STRING)) {objectNode.put(key, nextValue.asText());}} else if (attributeType1.equals(Constants.JSONOBJECT)) {ObjectNode objectNode = (ObjectNode) node;objectNode(objectNode, key, dkey, nextValue, attributeType1, attrs);} else if (attributeType1.equals(Constants.JSONARRAY)) {ObjectNode objectNode = (ObjectNode) node;arraryNode(objectNode, key, dkey, attributeType1, attrs);}}}}}}}/*** @param rootObjectNode      原始数据* @param rootKey       对象名称* @param attrKey* @param childJsonNode 对象里面的所有属性* @param attributeType* @param attrs*/public static void objectNode(ObjectNode rootObjectNode, String rootKey, String attrKey, JsonNode childJsonNode,String attributeType, List<Attr> attrs) {if (attributeType.equals(Constants.JSONOBJECT)) {Iterator<Map.Entry<String, JsonNode>> fields = childJsonNode.fields();while (fields.hasNext()) {Map.Entry<String, JsonNode> next = fields.next();String key = next.getKey();String dkey = attrKey + "." + key;//子属性nodeJsonNode nextValue = next.getValue();for (Attr attr : attrs) {if (dkey.equals(attr.getAttributeName())) {String attributeType1 = attr.getAttributeType();if (!attributeType1.equals(Constants.JSONOBJECT) && !attributeType1.equals(Constants.JSONARRAY)) {ObjectNode objectNode = rootObjectNode.with(rootKey);if (attributeType1.equals(Constants.DOUBLE)) {objectNode.put(key, nextValue.asDouble());} else if (attributeType1.equals(Constants.INTEGER)) {objectNode.put(key, nextValue.asInt());} else if (attributeType1.equals(Constants.LONG)) {objectNode.put(key, nextValue.asLong());} else if (attributeType1.equals(Constants.BOOLEAN)) {objectNode.put(key, nextValue.asBoolean());}} else if (attributeType1.equals(Constants.JSONOBJECT)) {ObjectNode objectNode = rootObjectNode.with(rootKey);objectNode(objectNode, key, dkey, nextValue, attributeType1, attrs);} else if (attributeType1.equals(Constants.JSONARRAY)) {ObjectNode objectNode = rootObjectNode.with(rootKey);arraryNode(objectNode, key, dkey, attributeType1, attrs);}}}}}}/*** 树节点处理名称拼接  查询sql的id必须按照升序排序 不然方法无效** @param all*/public static void tree(List<Attr> all) {//按照id升序 因为Attr是类似tree结构的数据,如果是object类型,一个属性的名称例如就是domain.id  为什么不直接拿id,因为不同节点id可能是string可能是integer,所以要通过对象.属性去重命名  外面匹配也是一样,如果有嵌套的数据,要自行处理名称和Attr重置后的名称匹配,才能得知真正类型是什么all.stream().sorted(Comparator.comparing(Attr::getId)).collect(Collectors.toList());for (Attr a : all) {if (a.getParentId().intValue() != -1) {setName(a, all);}}}public static void setName(Attr b, List<Attr> all) {for (Attr attribute : all) {if (b.getParentId().equals(attribute.getId())) {b.setAttributeName(attribute.getAttributeName() + "." + b.getAttributeName());}}}
}

主要难点,就是objectNode和arrayNode怎么去设置值,当时困扰了我很久,因为对ObjectMapper不熟悉,里面很多方法不知道,后面看了下源码才知道,主要的坑有以下几点:

  1. 所有的数据修改,都可以用ObjectNode.put方法去改,即使是arrayNode类型,之前不知道怎么去修改,妄想自己组装map去覆盖,结果失败。。
  2. 递归传递的值一定要捋清楚,很容易穿错原数据结构,比如对象套对象、对象套集合、集合套对象套集合等等这种很扭曲很恶心的结构,在针对对象和集合这两个类型卡我很久!!!
  3. JsonNode可以强转换为ObjectNode类型,之后就可以针对这个节点的值去修改,例如arrayNode我一直在查怎么修改,很多人都说删除原节点,自己写个新的节点加进去,这种很麻烦很麻烦很麻烦,尤其各种变态结构,极其容易出错(我没写成功过)
  4. ObjectNode.with、ObjectNode.withArray是object、array类型获取节点不同方式,里面填的是key名称,会去同一层找到这个key的所有属性返回,这个就是从源码看到的,百度我没找到,各个类去翻才找到。。。
  5. 如何去循环一个node,方法是JsonNode.fields();,JsonNode里面有很多方法,可以去源码看看,也有拿所有key的,但是 JsonNode.fields(); 能拿到所有的key-value键值对,其他的要么只能拿key,要么只能拿value,而且value还不是jsonNode类型,后面极其不好处理

就先说到这\color{#008B8B}{ 就先说到这}就先说到这
在下Apollo\color{#008B8B}{在下Apollo}在下Apollo
一个爱分享Java、生活的小人物,\color{#008B8B}{一个爱分享Java、生活的小人物,}一个爱分享Java、生活的小人物,
咱们来日方长,有缘江湖再见,告辞!\color{#008B8B}{咱们来日方长,有缘江湖再见,告辞!}咱们来日方长,有缘江湖再见,告辞!

ObjectMapper的objectNode、ArrayNode各种转换使用相关推荐

  1. 解决activiti中由模板转换的流程图连线名称缺失问题

    2019独角兽企业重金招聘Python工程师标准>>> 版本声明:Activiti 5.22.0 通常,由模板发布流程的代码大致如下: private Deployment conv ...

  2. java中的mapper是什么_Java使用ObjectMapper的简单示例

    一.什么是ObjectMapper? ObjectMapper类是Jackson库的主要类,它提供一些功能将数据集或对象转换的实现. 它将使用JsonParser和JsonGenerator实例来实现 ...

  3. 【Java】json与java对象转换,获得数据库自增主键,保存返回数据 (个人梳理)

    [Java]json与java对象转换,获得数据库自增主键,保存返回数据 (个人梳理) 模拟请求API 获得json数据,将json转换为java对象,再将java对象转换为list集合,再将list ...

  4. 7. Jackson用树模型处理JSON是必备技能,不信你看

    每棵大树,都曾只是一粒种子.本文已被 https://www.yourbatman.cn 收录,里面一并有Spring技术栈.MyBatis.JVM.中间件等小而美的专栏供以免费学习.关注公众号[BA ...

  5. java jackson_Jackson 框架的高阶应用

    Jackson 是当前用的比较广泛的,用来序列化和反序列化 json 的 Java 的开源框架.Jackson 社 区相对比较活跃,更新速度也比较快, 从 Github 中的统计来看,Jackson ...

  6. Activiti工作流使用之SpringBoot整合Activiti

    Activiti工作流使用之SpringBoot整合Activiti 文章目录 Activiti工作流使用之SpringBoot整合Activiti 一.springboot整合Activiti环境依 ...

  7. Spring默认使用的JSON工具--Jackson

    一.Jackson介绍 我们常用的json转换工具包括fastJson.Gson.Jackson等.其中Gson是Google所维护,功能全.fastJson特点是快,但是爆出几次的重大bug让人很难 ...

  8. java jackson教程_史上最全的Jackson框架使用教程

    简单介绍 别再使用 fastJson 了!漏洞天天报,Bug 修不完.快来拥抱 Jackson 吧! Jackson 是用来序列化和反序列化 json 的 Java 的开源框架.Spring MVC ...

  9. json.converter

    爬虫组件分析 目录 概述 需求: 设计思路 实现思路分析 1.ActivityProcessor 2.AssociationJsonConverter 3.BaseBpmnJsonConverter ...

最新文章

  1. “编程能力差,90%的人会输在这点上!”谷歌开发:其实都是在瞎努力
  2. 太 6 了!区块链包包、疫情防控大脑……程序员这样玩转区块链!
  3. Visual Assist X 10.8.2036的Crack破解补丁.2014.05.22 (General release.)
  4. linux下tomcat的安装和配置
  5. mysql读取求和_MySQL从单独的表中获取求和值
  6. 计算机用户win7修改不,Win7电脑时间改不了的解决方法
  7. 转载构造函数与拷贝构造函数
  8. 检验mysql安装成功win7,手把手教你win7系统成功安装 RMySQL的处理对策
  9. java制作大富翁游戏_JAVA大富翁游戏的设计+流程图+总结体设计图-论文.doc
  10. 使用ZbarSDK实现扫描二维码以及条形码功能(iOS)
  11. dsp呼吸灯C语言编程,pwm呼吸灯原理及程序分享
  12. 高效办公之高效学习技巧:艾宾浩斯遗忘曲线及学习策略分享
  13. python功能主菜单_Pycharm主菜单学习
  14. [渝粤教育] 天津师范大学 教育心理学(唐卫海) 参考 资料
  15. 5秒内克隆你的声音,并生成任何内容,这个工具细思极恐...还特么的开源~
  16. 【附源码】Java计算机毕业设计架构的博客平台设计(程序+LW+部署)
  17. 请不要在该奋斗的年纪选择了安逸
  18. 取原始数组中的指定数据push新数组
  19. 锐速ServerCheck序列号生成原理
  20. 深入理解Java虚拟机读书笔记七

热门文章

  1. 什么密码,永远无法被黑客攻破?
  2. 写给想考金融硕士的学弟学妹
  3. 基于python的国内外研究现状_国内外研究现状评述
  4. 创纪录15支球队参与 3大球星领衔NBA新春贺岁
  5. bq27541 写入senc文件
  6. 一个表中的字段值用作另一个表的In查询条件
  7. java毕业设计‘大学生心理健康咨询管理系统mybatis+源码+调试部署+系统+数据库+lw
  8. 人的记忆组成图(原创整理,转载请注明)
  9. oracle连现金流量表都没有,现金流量表里面的数据地方都是空白的 没有数字
  10. 广告业务系统 之 敏捷交付 —— “基于 Docker 容器同机部署”