Simplify-Core --Json解析(Json parser)
2017-07-16 23:17
190 查看
在上一篇文章中,我们看到了一个java对象是怎么转换成json规范的字符串,这一次是反过来,从json字符串解析json内容,并且合成java bean,先上我的Simplify项目地址项目,欢迎路过的大牛对项目提出建议。
解析代码逻辑大致如下:
总的来说就是碰到不同的字符 需要做不同的处理,最后的jsonObject对象便是从String转换成java对象的第一步,当然,我们还需要把jsonObject 对象转换成我们实际需要的类,这里又用到了codec处理器。
这里主要用到的还是反射机制,在parse方法中,第一个object是不准确的数据类型,是需要我们待处理的字段,第二个参数method是我们实际业务场景中 该字段的set方法,我们通过反射可以知道它实际的数据类型,并作针对的处理,如果该字段是array,我们还需要知道它的泛型。
以Number数据类型为例,部分代码如下:
当拿到真正的值,我们就可以通过反射调用set方法进行赋值,也就完成了整个json解析的流程。
整个过程讲的比较粗糙,可以参照源码和测试用例来看,项目还在不断的完善中,而且也不止json这一块内容,Simplify就是希望能减少显式的java代码,提高编程效率,精力有限,有问题随时指出,谢谢~!
项目地址:https://github.com/lovejj1994/Simplify-Core
还是再贴一下json框架的架构图,因为不管是解析还是生成,都跟这个架构有关系。先对json字符串进行解析
要转换成json对象,你首先需要对json字符串进行解析,解析的大致原理在于先给一个栈,然后对不同的字符做不同的处理,比如你碰到一个大括号({),你应该知道json需要一个map对象去装key,value值,当你碰到一个中括号([),你应该知道需要一个数组对象去装数组等等,因为字符串从前往后解析,所以需要栈结构,利用入栈,出栈来完成解析逻辑,打个比方,当你碰到大括号,你需要先把一个JsonObject(实质是map)压入栈,然后继续解析后面的字符串,这个字符串必定是key值,并且将这个字符串压入栈,后面一会碰到冒号(:),说明后面是value,你需要读取这个value值并压入栈,最后,你碰到 后大括号(}),说明你需要把前面的key,value,以及JsonObject依次弹出栈,并把key,value值放入JsonObject中,然后把JsonObject重新压入栈。如果json字符串符合规范的话,最后你的栈应该只剩下一个JsonObject,这时候,你的解析工作就算完成了,当然,实际情况不止那么简单,所以会用到递归逐层解析。解析代码逻辑大致如下:
public JsonObject parseObject(String text) { Stack<Object> stacks = new Stack<>(); String status = Const.BEGIN; char[] chars = text.toCharArray(); if (chars.length > 0) { if (!(Const.PRE_BRACE_CHAR == chars[0])) { throw new RuntimeException("The structure of jsonString is wrong "); } for (int i = 0; i < chars.length; i++) { switch (chars[i]) { //碰到 { case Const.PRE_BRACE_CHAR: { status = Const.KEY; JsonObject jo = new JsonObject(); stacks.push(jo); break; } //碰到 } case Const.POST_BRACE_CHAR: { groupJsonObject(stacks, status); break; } //碰到 " case Const.SINGLE_QUOTES_CHAR: { if (Const.KEY.equals(status)) { pushNewString(stacks); } else if (Const.VALUE.equals(status)) { pushNewString(stacks); status = Const.READINGSTRING; } break; } //碰到 : case Const.COLON_CHAR: { if (!status.equals(Const.READINGSTRING)) { status = Const.VALUE; } else { readValue(stacks, chars, i); } break; } //碰到 , case Const.COMMA_CHAR: { groupJsonObject(stacks, status); if (JsonArray.class == stacks.peek().getClass()) { if (i + 1 < chars.length) { char c = chars[i + 1]; if (c != Const.SINGLE_QUOTES_CHAR) { status = Const.VALUE; } else { status = Const.KEY; } } else { throw new RuntimeException("The structure of jsonString is wrong "); } } else { status = Const.KEY; } break; } //碰到 [ case Const.PRE_BRACKET_CHAR: { JsonArray<Object> jsonArray = new JsonArray<>(); stacks.push(jsonArray); break; } //碰到 ] case Const.POST_BRACKET_CHAR: { if (JsonObject.class == stacks.peek().getClass()) { JsonObject jsonObject = (JsonObject) stacks.pop(); if (JsonArray.class == stacks.peek().getClass()) { JsonArray<Object> jsonArray = (JsonArray<Object>) stacks.pop(); jsonArray.add(jsonObject); stacks.push(jsonArray); } } else if (StringBuffer.class == stacks.peek().getClass()) { StringBuffer value = (StringBuffer) stacks.pop(); String s = value.toString(); if (JsonArray.class == stacks.peek().getClass()) { JsonArray<Object> jsonArray = (JsonArray<Object>) stacks.pop(); addValueForJsonArray(jsonArray, s); stacks.push(jsonArray); } } break; } default: { if (Const.VALUE.equals(status)) { pushNewString(stacks); } if (Const.READINGSTRING.equals(status)) { } else { status = Const.READING; } readValue(stacks, chars, i); break; } } } } if (stacks.size() != 1) { throw new RuntimeException("The structure of jsonString is wrong "); } else { return (JsonObject) stacks.pop(); } }
总的来说就是碰到不同的字符 需要做不同的处理,最后的jsonObject对象便是从String转换成java对象的第一步,当然,我们还需要把jsonObject 对象转换成我们实际需要的类,这里又用到了codec处理器。
codec不仅负责生成,也负责解析
我们知道,在Ijson接口中,除了writeJsonString用于生成json,还有一个parse方法,用于将解析出来的jsonObject转换成我们实际业务场景需要的类,而不仅仅是个简单的map结构类型。Object parse(Object o, Method m);
这里主要用到的还是反射机制,在parse方法中,第一个object是不准确的数据类型,是需要我们待处理的字段,第二个参数method是我们实际业务场景中 该字段的set方法,我们通过反射可以知道它实际的数据类型,并作针对的处理,如果该字段是array,我们还需要知道它的泛型。
以Number数据类型为例,部分代码如下:
@Override public Object parse(Object o, Method m) { Class<?> parameterTypes = getParameterTypes(m); //如果参数是map,我们需要知道它泛型,就是真正的字段类型 if (Map.class.isAssignableFrom(parameterTypes)) { Type actualTypeArguments = getActualTypeArguments(m); return numberParse(o, (Class) actualTypeArguments); } return numberParse(o, parameterTypes); } //具体的Number解析逻辑,每一种数字类型都需要兼顾到 private Object numberParse(Object o, Class parameterTypes) { if (parameterTypes == int.class || parameterTypes == Integer.class) { if (o instanceof Integer) { return o; } else if (o instanceof BigDecimal) { return ((BigDecimal) o).intValue(); } else if (o instanceof BigInteger) { return ((BigInteger) o).intValue(); } return o; } if (parameterTypes == long.class || parameterTypes == Long.class) { if (o instanceof Long) { return o; } else if (o instanceof BigDecimal) { return ((BigDecimal) o).longValue(); } else if (o instanceof Integer) { return ((Integer) o).longValue(); } } if (parameterTypes == short.class || parameterTypes == Short.class) { if (o instanceof Short) { return o; } else if (o instanceof BigDecimal) { return ((BigDecimal) o).shortValue(); } else if (o instanceof Integer) { return ((Integer) o).shortValue(); } } if (parameterTypes == double.class || parameterTypes == Double.class) { if (o instanceof Double) { return o; } else if (o instanceof BigDecimal) { return ((BigDecimal) o).doubleValue(); } else if (o instanceof Integer) { return ((Integer) o).doubleValue(); } } if (parameterTypes == float.class || parameterTypes == Float.class) { if (o instanceof Float) { return o; } else if (o instanceof BigDecimal) { return ((BigDecimal) o).floatValue(); } else if (o instanceof Integer) { return ((Integer) o).floatValue(); } } if (parameterTypes == byte.class || parameterTypes == Byte.class) { if (o instanceof Byte) { return o; } else if (o instanceof BigDecimal) { return ((BigDecimal) o).byteValue(); } else if (o instanceof Integer) { return ((Integer) o).byteValue(); } } throw new JsonException("unsupport type " + parameterTypes); }
当拿到真正的值,我们就可以通过反射调用set方法进行赋值,也就完成了整个json解析的流程。
整个过程讲的比较粗糙,可以参照源码和测试用例来看,项目还在不断的完善中,而且也不止json这一块内容,Simplify就是希望能减少显式的java代码,提高编程效率,精力有限,有问题随时指出,谢谢~!
相关文章推荐
- iOS开发——网络篇——JSON和XML,NSJSONSerialization ,NSXMLParser(XML解析器),NSXMLParserDelegate,MJExtension (字典转模型),GDataXML(三方框架解析XML)
- Core JSON及JSON解析
- SparkCore解析json数据fastjson
- Jackson配置属性(JsonParser解析相关配置属性)
- UI 13 数据解析 Parser DOM JSON
- flex中使用corelib ActionScript 3 Library sdk包解析json数据
- [转]flex中使用corelib ActionScript 3 Library sdk包解析json数据
- xmlpullparser解析json文件
- Simplify-Core -- java对象转换成Json(Json generator)
- Gson-JsonParser解析Json字符串
- iOS 【网端数据解析 JSON(MJExtension)& XML(NSXMLParser/GDataParser)】
- flex中使用corelib ActionScript 3 Library sdk包解析json数据
- 灵活组装Json的数据使用Gson的JsonParser和JsonReader解析Json详解例子
- 使用Scala Parser解析JSON
- 灵活组装Json的数据使用Gson的JsonParser和JsonReader解析Json详解例子
- Json和xmlpullparser解析的联系和区别
- 灵活组装Json的数据使用Gson的JsonParser和JsonReader解析Json详解例子
- PHP serialize & JSON 解析
- json和bean的转换工具Jackson ObjectMapper类使用解析
- json数据前台解析 修改check属性用prop()