{ "status":"200", "res":[ { "province":"山东省", "city":"潍坊市", "name":"兰州拉面馆", "prop":{ "type":"餐饮单位", "level":1 }, "month_data":[ {"month":"1","amount":18518.5}, {"month":"2","amount":18519.5}, {"month":"3","amount":18517.5}, {"month":"4","amount":18516.5} ] }, { "province":"山东省", "city":"淄博市", "name":"电瓶批发", "prop":{ "type":"其它", "level":2 }, "month_data":[ {"month":"1","amount":28518.5}, {"month":"2","amount":28519.5}, {"month":"3","amount":28517.5}, {"month":"4","amount":28516.5} ] } ] }
我的办法如果read出来 然后 JsonUtils 工具类转换 list
内容一旦很多,就容易java help space
测试入口我采用的是com.google.gson.stream.JsonReader这个工具类是按照符号顺序读取的,不是一下加载到内存中的。
public static void main(String[] args) throws Exception { // 创建jsonReader JsonReader jsonReader = new JsonReader(new FileReader(new File("C:\Users\Wsong\Desktop\test.json"))); // 定位到指定的数组节点 如果本身就是个数组 传入$,如果本身是个对象可以传入null findRootArray(jsonReader, "$.res"); // 传入jsonReader,传入key值 ArrayList结果> lists = jsonArr2list(jsonReader, Arrays.asList("$.province", "$.city", "$.name", "$.prop.type", "$.prop.level")); // 得到每一行的数组结果,我这里为了讲明白,没有设置数据类型 都用的string System.out.println(lists); }
[[山东省, 潍坊市, 兰州拉面馆, 餐饮单位, 1, 18516.5], [山东省, 淄博市, 电瓶批发, 其它, 2, 28516.5]]代码
package com.ws.tools; import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; import com.jayway.jsonpath.DocumentContext; import com.jayway.jsonpath.JsonPath; import com.ws.tools.dto.ColumnEntry; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.Reader; import java.util.*; public class JsonReaderUtils { private static Gson gson = new Gson(); public static void main(String[] args) throws Exception { // 创建jsonReader JsonReader jsonReader = new JsonReader(new FileReader(new File("C:\Users\Wsong\Desktop\test.json"))); // 定位到指定的数组节点 findRootArray(jsonReader, "$.res"); // 传入jsonReader,传入key值 ArrayList> lists = jsonArr2list(jsonReader, Arrays.asList("$.province", "$.city", "$.name", "$.prop.type","$.month_data[3].amount")); // 得到每一行的数组结果,我这里为了讲明白,没有设置数据类型 都用的string System.out.println(lists); } public static ArrayList
> jsonArr2list(JsonReader jsonReader, List
jsonKeys) throws Exception { JsonToken peek; int startObj = 0; int endObj = 0; // 组装最后的结果 ArrayList > res = new ArrayList<>(); StringBuilder sb = new StringBuilder(); // 防止循环无法跳出 int i = 0; while (true) { // 这个方法是返回json文件中下一个标签 peek = jsonReader.peek(); // 如果下一个标签是9 代表json文档结束 就退出循环了返回了 if (peek.ordinal() == 9 || i > 10000000) { break; } // 遇到一个"{" startObj++ if (peek.ordinal() == 2) { startObj++; } // 遇到一个"}" endObj++ if (peek.ordinal() == 3) { endObj++; } // 读取到每个标签 String val = peekAndRead(peek, jsonReader); // 对数据进行处理,看不懂可以注掉这段代码 if (StringUtils.endsWith(sb, "{")) { val = StringUtils.removeStart(val, ","); } // 拼接 json sb.append(val); // 如果 遇到的 "{" 和遇到的 "}" 数量相同 说明一个对象已经读取完成,该读下一个对象了 if (startObj == endObj && startObj != 0) { // 解析到的数据 List
parser = parser(sb.toString(),jsonKeys); res.add(parser); sb = new StringBuilder(); startObj = 0; endObj = 0; i = 0; } i++; } return res; } private static List parser(String json,List columns) { List splitLine = new ArrayList<>(); // jsonpath 解析支持 $.key $key1.$key2 $key[0].$key1 DocumentContext document = JsonPath.parse(json); String tempValue; for (String columnIndex : columns) { try { tempValue = document.read(columnIndex,String.class); } catch (Exception ignore) { ignore.printStackTrace(); tempValue = null; } splitLine.add(tempValue); } return splitLine; } private static void findRootArray(JsonReader jsonReader, String arryRootKey) throws Exception { // arryRootKey==$ 表明,数据根节点就是个数组,直接开启数组 if ("$".equalsIgnoreCase(arryRootKey)) { jsonReader.beginArray(); } else if (StringUtils.isBlank(arryRootKey)) { // 如果 arryRootKey==$ 说明是个对象,不用管 } else { // 按层级查询 数组节点 String[] keys = StringUtils.removeStart(arryRootKey, "$.").split("\."); for (String s : keys) { JsonToken peek; int i = 10000; while (jsonReader.hasNext()) { peek = jsonReader.peek(); if (peek.ordinal() == 4) { if (jsonReader.nextName().equalsIgnoreCase(s)) { jsonReader.beginArray(); break; } } else { peekAndRead(peek, jsonReader); } i--; if (i == 0) { throw new Exception("json key 解析异常"); } } } } } private static String peekAndRead(JsonToken p, JsonReader jsonReader) throws Exception { switch (p) { case BEGIN_OBJECT: jsonReader.beginObject(); return "{"; case END_OBJECT: jsonReader.endObject(); return "}"; case BEGIN_ARRAY: jsonReader.beginArray(); return "["; case END_ARRAY: jsonReader.endArray(); return "]"; case NAME: return ","" + jsonReader.nextName() + "":"; case BOOLEAN: return jsonReader.nextBoolean() + ""; case NULL: jsonReader.nextNull(); return "null"; case STRING: case NUMBER: return """ + jsonReader.nextString() + """; case END_DOCUMENT: throw new Exception("json文件解析已经完成~"); default: throw new Exception("不认识的json符号 [" + p.ordinal() + "]"); } } }