ObjectMapper的objectNode、ArrayNode各种转换使用

在这里插入图片描述

说明

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

为什么写这个代码
需求要求,有一段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)) {
                        //第一层的key
                        objectNode(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;
                    //子属性node
                    JsonNode 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;
                //子属性node
                JsonNode 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}{ 就先说到这} 就先说到这
在下 A p o l l o \color{#008B8B}{在下Apollo} 在下Apollo
一个爱分享 J a v a 、生活的小人物, \color{#008B8B}{一个爱分享Java、生活的小人物,} 一个爱分享Java、生活的小人物,
咱们来日方长,有缘江湖再见,告辞! \color{#008B8B}{咱们来日方长,有缘江湖再见,告辞!} 咱们来日方长,有缘江湖再见,告辞!

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用以下的Java代码将JSON文件转换为Drools规则文件: ```java import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import org.drools.template.ObjectDataCompiler; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; public class JsonToDrlConverter { public static void main(String[] args) throws IOException { // Read JSON file as string String jsonStr = new String(Files.readAllBytes(Paths.get("rules.json"))); // Convert JSON string to object ObjectMapper objectMapper = new ObjectMapper(); ObjectNode rootNode = objectMapper.readValue(jsonStr, ObjectNode.class); // Convert JSON object to Drools rules ObjectDataCompiler compiler = new ObjectDataCompiler(); String drlStr = compiler.compile(getData(rootNode), getTemplate(), getBindings()); // Write Drools rules to file File outputFile = new File("rules.drl"); Files.write(outputFile.toPath(), drlStr.getBytes()); } private static Map<String, Object> getBindings() { Map<String, Object> bindings = new HashMap<>(); bindings.put("packageName", "com.example.rules"); return bindings; } private static String getTemplate() { return "package [[packageName]];\n" + "import com.example.Fact;\n" + "rule \"[[ruleName]]\"\n" + "when\n" + "$fact : Fact(\n" + "$[[condition.property]] : [[condition.property]] [[condition.operator]] [[condition.value]])\n" + "then\n" + "System.out.println(\"[[ruleName]] fired!\");\n" + "end\n"; } private static Object[] getData(ObjectNode rootNode) { ArrayNode rulesNode = (ArrayNode) rootNode.get("rules"); Object[] data = new Object[rulesNode.size()]; for (int i = 0; i < rulesNode.size(); i++) { ObjectNode ruleNode = (ObjectNode) rulesNode.get(i); String ruleName = ruleNode.get("name").asText(); ObjectNode conditionNode = (ObjectNode) ruleNode.get("condition"); String property = conditionNode.fieldNames().next(); String operator = conditionNode.get(property).get("operator").asText(); String value = conditionNode.get(property).get("value").asText(); data[i] = Map.of("ruleName", ruleName, "condition", Map.of("property", property, "operator", operator, "value", value)); } return data; } } ``` 这个简单的例子假设您有一个JSON文件,它包含一个名为“rules”的数组,其中每个元素都是一个规则对象,包含名称和条件。规则条件是一个对象,其中包含一个属性名称、一个操作符和一个值。例如: ```json { "rules": [ { "name": "Rule 1", "condition": { "age": { "operator": ">", "value": "18" } } }, { "name": "Rule 2", "condition": { "gender": { "operator": "==", "value": "female" } } } ] } ``` 这个例子使用Drools模板语言来生成规则文件。模板中的占位符将使用数据数组中的值进行替换。在模板中,您可以使用任何Drools规则语言构造。此例中,规则条件将被转换为一个简单的规则语句。运行此示例将生成以下Drools规则文件: ```drools package com.example.rules; import com.example.Fact; rule "Rule 1" when $fact : Fact( $age : age > 18) then System.out.println("Rule 1 fired!"); end rule "Rule 2" when $fact : Fact( $gender : gender == "female") then System.out.println("Rule 2 fired!"); end ``` 请注意,该示例中的规则语句非常简单,并且只考虑了一个条件属性。您可以根据您的需要修改模板和数据来生成更具复杂性的规则文件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值