Jackson解析与生成Json文件(Jackson常见操作、读取文件、设置结点)

小编这两天的工作是把某个Json文件做格式转换,提取其中有用的信息。所以需要解析原Json文件,获取其Json结点和属性值,再拼装到另一个Json文件并输出。

一、解析Json文件

0. 简介

想要生成JsonNode对象都要先生成ObjectMapper类对象,它是产生Json结点的工厂。

ObjectNode是对象结点,可以存入对象属性。如 { "name":"Lilei", "age":"18", "school":"HNU" }

ArrayNode是数组结点,用于存放JsonNode数据。如[ "Lilei", "XiaoHong", {"nm1": "Jay", "nm2": "Kong"} ]

同时属性值和数组值都可以嵌套对象或数据,并且JsonNode是ObjectNode和ArrayNode的父接口。

1. 读取文件

读取文件时,传入文件输入流,文件对象或者文本内容都可以,支持灵活处理。

 

ObjectMapper mapper= new ObjectMapper();
JsonNode rootNode = mapper.readValue(stringName, JsonNode.class);    /*方法1*/
JsonNode rootNode = mapper.readTree(data);        /*方法2*/

2. 获取属性或子节点

以下向大家展示了如何获取结点,或某个域(field)对应的值(value),以及遍历不清楚子节点是对象结点还是数组结点时的访问方法。

要注意的是,获取子节点有path和get两种方法,他们在功能上几乎相同。但区别如下:

path:路径访问安全,当访问的结点不存在时返回“MissingNode”,我将其理解为没有任何属性值的结点,也可以通过asText()转换为String类型,值为空字串;当访问的属性无效时同样返回空字串""。

优势是不知道多层子节点的值是否一定存在时可以连续使用path,若不存在一律返回"";但不能判断结点是否存在。

get:路径访问不安全,其访问结点路径或属性无效时返回null,故使用连续使用get访问时,若路径不存在会出现空指针异常

优势是可以用是否为null判断结点是否存在。

访问技巧:不知道节点路径上是否所有节点都存在,可以使用

JsonNode temp = xxxNode.path("prop1").path("prop2").....get("propN");

if (null != temp) { do something... } 这样的方式安全得到不一定存在的节点

//获取结点
JsonNode jsonNode = rootNode.path("属性名");    /*通过属性名获取子节点,且路径访问安全*/
JsonNode jsonNode = rootNode.path("属性名1").path("属性名2").path("属性名3");    /*可连续使用*/
JsonNode jsonNode = rootNode.get("属性名");    /*通过属性名获取子节点*/

//获取属性
String jsonData = jsonNode.path("属性名").asText();    /*获取该属性的value值*/
String jsonData = jsonNode.path("属性名").asInt();
...    /*以下同理*/

//遍历数组结点
for (JsonNode jsonNode: NodeArray) {
    ...
}

//在不知道某个结点是对象结点还是数组结点时的遍历方法
//其中JsonNode是对象结点ObjectNode和数组结点ArrayNode的父接口
if (jsonNode instansof ArrayNode) {
    for (JsonNode jsonNode: NodeArray) {
    ...
} else {     /*else if (jsonNode instansof ObjectNode)*/
    ...
}

二、生成Json文件

1. 生成ObjectNode和ArrayNode

很多时候我们需要自己将信息拼装,得到目的json字串,所以对于结点的生成和属性注入也需要掌握

ObjectMapper mapper = new ObjectMapper();

//生成对象结点
ObjectNode objNode = mapper.createObjectNode();
objNode.put("属性名", 属性值);    /*在jdk1.8中,简单值用put设置*/
objNode.set("属性名", 子节点);    /*在jdk1.8中,子节点用set设置*/

//生成数组结点
ArrayNode arrNode = mapper.createArrayNode();
arrNode.add("属性或子节点");    /*数组结点添加元素不做简单值和结点类的区分*/

2. 将json写入文件

OutputStream outputStream= new FileOutputStream(new File("path"));
objectMapper.writeValue(outputStream, data);

三、实例讲解(你也可以不读题设直接看后文示例代码)

假设有Json数据如下,我们的任务是:将SentenceGroup中Sentence的content字段抽取,并重新拼装。不过Sentence的属性值可能是ObjectNode, 也可能是ArrayNode。

"SentenceGroup": {
    "id": 12345,
    "book": RenaiEnglish,
    "Sentence": {
        "id": 12346,
        "updater": Mario,
        "content": "I like apple"
    }
}

"SentenceGroup": {
    "id": 12345,
    "book": RenaiEnglish,
    "Sentence": [
        {
            "id": 12346,
            "updater": Mario,
            "content": "I like orange"
        },
        {
            "id": 12347,
            "updater": Kate,
            "content": "I like banana"
        }
    ]
}

示例代码:

ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(data);    /*设跟根节点是SentenceGroup*/

JsonNode resultNode = null;
JsonNode sentences = rootNode.path("Sentence");
if (sentence instanceof ArrayNode) {
    resultNode = mapper.createArrayNode();    /*创建ArrayNode对象*/
    for (JsonNode jsonNode: sentences) {
        ObjectNode sentNode = mapper.createObjectNode();        /*声明新结点*/
        String content = jsonNode.path("content").asText();    /*获取属性值*/
        sentNode.put("content", content)        /*存储属性值,存储结点得用set*/

        //给ArrayNode添加元素
        //操作1结果是 [{"content":"I like orange"}, {"content":"I like banana"}]
        ((ArrayNode) resultNode).add(sentNode);
        
        //操作2结果是 ["I like orange", "I like banana"],少一层对象结点的嵌套
        ((ArrayNode) resultNode).add(content);
    }
} else {
    resultNode = mapper.createObjectNode();    /*创建ObjectNode对象*/
    ((ObjectNode)resultNode).put("content", content)
}

//输出resultNode略
//...

 

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值