fasterxml jaskson 的使用
- 为啥要撰写这玩儿?
- 解析json格式字符串
- 判断是否是json格式字符串
- 解析原理与解析函数
- 如何使用该函数?
为啥要撰写这玩儿?
由于SpringBoot的依赖默认使用fasterxml-jaskson(可能是由于不想使用其他json处理包,也不知道为啥,即使其他jar包用法很简单,但是本着jar包的简洁性,还是想研究一下fasterxml-jaskson对json数据格式的创建和解析)。既然SpringBoot使用了这个jaskson依赖,一定也有它的道理。
后面发现,用这个玩意儿,可以不用创建POJO对象。这估计也是我想研究该类方法的一个原因吧。
解析json格式字符串
先上代码:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
public class TestMain {
public static final ObjectMapper MAPPER = new ObjectMapper();
public static void main(String[] args) {
// 定义json字符串,格式中的“需要进行转意
String jsonStr = "{\"username\":\"hello\", \"password\": \"world\"}";
try {
// JsonParser 对象中有解析json格式的方法
// 该方法也可以用来验证 传入的字符串是否是json格式的字符串
// 如果不是json格式的字符串,则会抛出异常(毕竟要抛出异常)。
JsonParser parser = MAPPER.createParser(jsonStr);
// TODO ...编写解析方法
// 该部分代码将会在后面添加
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
maven库官网:https://mvnrepository.com/
fasterxml-json maven坐标:<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.13.4.2</version> </dependency>
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.13.4</version> </dependency>
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.13.4</version> </dependency>
不要问我怎么知道需要这三个,因为这个:
推理呗!并且根据上面可以得到,jackson-databind.jar这个包是依赖jackson-annotations.jar 和 jackson-core.jar这两个包的!!
判断是否是json格式字符串
其中的代码片:
try {
JsonParser parser = MAPPER.createParser(jsonStr);
catch(IOException e){
throw new RuntimeException(e);
}
以上这段代码可以用来验证传入的字符串是否是json格式的字符串毕竟如果解析不正确,会抛出异常。
解析原理与解析函数
fasterxml-jackson是如何判断每个符号的呢?请看下面的截图:
嗯~,熟悉的味道。该枚举类定义了START_OBJECT、END_OBJECT等常量,就是用来判断传进来的字符串。但是目前没有搞懂NOT_AVAILABLE和VALUE_EMBEDDED_OBJECT具体怎么用,如果知道的博友,可以交流哈。
开始使用这个方法进行解析json字符串时,真的只是为了学习!没有其他的本意。但是,这个fasterxml-jackson包解析字符串确实比较麻烦。为此我专门研究了一个方法,给出代码:
public static void parse(JsonParser parser, JsonNode objectNode){
try {
ObjectNode objNode = null;
ArrayNode arrNode = null;
if(objectNode instanceof ObjectNode) {
objNode =(ObjectNode) objectNode;
}else{
arrNode = (ArrayNode) objectNode;
}
//只要是正规的json格式的字符串,则一定会有key
String key = null;
while(!parser.isClosed()) {
JsonToken jsonToken = parser.nextToken();
// 这里只过滤我们感兴趣的字段
//
switch (jsonToken){
case FIELD_NAME:
key = parser.getCurrentName();
break;
case VALUE_STRING:
String value = parser.getValueAsString();
objNode.put(key, value);
break;
case VALUE_NUMBER_FLOAT:
// 为了使得表示浮点数足够大,因此这里用getDoubleValue()来获取。
objNode.put(key, parser.getDoubleValue());
break;
case VALUE_NUMBER_INT:
objNode.put(key, parser.getIntValue());
break;
case VALUE_TRUE:
case VALUE_FALSE:
objNode.put(key, parser.getBooleanValue());
break;
case VALUE_NULL:
// put方法中没有可以负值null的接口,这里暂且用"null"代替。
objNode.put(key, "null");
break;
case START_OBJECT:
// 碰到值是对象的类型,则新建一个JsonNode类型的对象
JsonNode embededObj = MAPPER.createObjectNode();
if(objectNode instanceof ObjectNode) {
// springboot2.x.x的版本需要传个null,
// 即:"!objNode.isEmpty(null)"
if (!objNode.isEmpty()) {
objNode.set(key, embededObj);
// 递归调用处理,这里不能够和外层的else,中的parse()合并来写,因为,如果是处理根{},则不需要递归调用!
parse(parser, embededObj);
}
} else {
arrNode.add(embededObj);
// 递归调用处理
parse(parser, embededObj);
}
break;
case END_OBJECT:
// 如果对象解析结束则推出该层函数的解析
// 递归处理出口,直接返回return
return;
case START_ARRAY:
if(objectNode instanceof ObjectNode) {
// 当{}内部有[],就需要进入该判断。
if (!objectNode.isEmpty()) {
JsonNode arrayObj = MAPPER.createArrayNode();
objNode.set(key, arrayObj);
parse(parser, arrayObj);
// ((ObjectNode)objectNode).putArray(key);
}
}else{
// 如果根是[],并且是第一次进入该代码段,即objectNode是空的,则跳过。
if(!objectNode.isEmpty()) {
JsonNode arrObj = MAPPER.createArrayNode();
arrNode.add(arrObj);
// 递归调用处理,如果[]内部有{}则交给递归处理。
parse(parser, arrObj);
}
}
break;
case END_ARRAY:
// 如果数组解析结束则推出该层函数的解析
// 递归处理出口,直接返回return
return;
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
以上代码是一个递归调用的代码,如果有余力,看看改成栈的形式,那是极好的。
如何使用该函数?
MAPPER.createParser()方法提供了多种解析的入口,大家可以自行选用。
public static void main(String[] args) {
String jsonStr = "{\"username\":\"hello\", \"password\": \"world\", \"isNull\": null, \"embededObj\": {\"prop1\":\"value1\", \"prop2\": \"value2\"}, \"arrayObj\": [{\"objK1\": \"val1\"},{\"objK2\": \"val2\"}]}";
try {
JsonParser parser = MAPPER.createParser(jsonStr);
// 可以从文件中解析,MAPPER.createParser(xxx)支持多种解析的入口。
// JsonParser parser = MAPPER.createParser(new File("xxxx.json"));
// 如果根是{} 则用MAPPER.createObjectNode()
ObjectNode objectNode = MAPPER.createObjectNode();
// 如果根是[] 则用MAPPER.createArrayNode()
ArrayNode arrayNode = MAPPER.createArrayNode();
parse(parser, objectNode);
parse(parser, arrayNode);
System.out.println(objectNode);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
以上就是对fasterxml-jackson使用的初步探索,大家有其他的想法可以多多交流哈。