解析超大JSON文件
将超大JSON文件导出到Excel中,采用JsonToken解决方案:
package com.godfrey.poi.util;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.MappingJsonFactory;
import java.io.File;
/**
* @author godfrey
* @since 2021-12-05
*/
public class ParseJsonUtil {
public static void main(String[] args) throws Exception {
JsonFactory f = new MappingJsonFactory();
JsonParser jp = f.createJsonParser(new File("F:/FeaturesToJSON.json"));
JsonToken current;
current = jp.nextToken();
if (current != JsonToken.START_OBJECT) {
System.out.println("Error: root should be object: quiting.");
return;
}
while (jp.nextToken() != JsonToken.END_OBJECT) {
String fieldName = jp.getCurrentName();
// move from field name to field value
current = jp.nextToken();
if ("features".equals(fieldName)) {
if (current == JsonToken.START_ARRAY) {
// For each of the records in the array
while (jp.nextToken() != JsonToken.END_ARRAY) {
// read the record into a tree model,
// this moves the parsing position to the end of it
JsonNode node = jp.readValueAsTree();
// And now we have random access to everything in the object
System.out.println("field1: " + node.get("field1").asText());
System.out.println("field2: " + node.get("field2").asText());
}
} else {
System.out.println("Error: records should be an array: skipping.");
jp.skipChildren();
}
} else {
System.out.println("Unprocessed property: " + fieldName);
jp.skipChildren();
}
}
}
}
JSONObject解析报错:java.lang.ClassCastException: net.sf.ezmorph.bean.MorphDynaBean
背景
当利用net.sf.json.JSONObject
中的toBean
方法把字符串解析为JSONObject对象时,如果这个对象中的属性里含有复杂的对象,那么我们在获取这个复杂对象时会报错:java.lang.ClassCastException: net.sf.ezmorph.bean.MorphDynaBean cannot be cast to XXX
解决方案
-
json转化为带有list集合的复杂对象时出现
ClassCastException
异常新建map对象并用list集合的名称作为key,list集合中复杂对象的Class作为value值put到map中。在将json对象转化为bean对象时,将这个map作为最后一个参数传入到
toBean
方法里面进行解析转化,具体代码如下://retStr为调用接口返回的String类型的json格式字符串,其中里面存放着一个叫做flights的复杂集合对象,FlightResponse是自己封装的最外层的对象。 //retStr 格式为: {"resp":{"msg":"成功","code":"00000000","flights":[{"flightArrName":"重庆/江北","companyName":"CA","canFavFlag":"0","fltProStatus":"到达","flightNowStation":"100","flightId":"71434393","remark":"","flightDepName":"重庆/江北","flightNO":"CA4487","fltDepTime":"2022-04-21 14:55","fltArrTime":"2022-04-21 17:58","flightDeptimePlan":"2022-04-21 14:55","fltDepTimeS":"2022-04-21 15:00","delayReason":"","flightDep":"CKG","flightTerminal":" ","flightHTerminal":" ","flightDate":"2022-04-21","fltDepTimeE":"--","flightModel":"737","flightStatus":"到达","modelType":"窄体","isStopOver":"N","fltArrTimeE":"2022-04-21 17:59","isFav":"0","flightArrtimePlan":"2022-04-21 17:58","flightStatusFlag":"5","flightArr":"CKG","fltProgress":"100","fltTotalTime":10800000,"isShare":"N","fltArrTimeS":"2022-04-21 18:00"},{"flightArrName":"西双版纳/嘎洒","companyName":"CA","canFavFlag":"0","fltProStatus":"到达","flightNowStation":"100","flightId":"71805686","remark":"","flightDepName":"重庆/江北","flightNO":"CA4487","fltDepTime":"2022-04-21 19:30","fltArrTime":"2022-04-21 21:23","flightDeptimePlan":"2022-04-21 19:30","fltDepTimeS":"2022-04-21 19:00","delayReason":"天气原因","flightDep":"CKG","flightTerminal":" ","flightHTerminal":" ","flightDate":"2022-04-21","fltDepTimeE":"--","flightModel":"737","flightStatus":"到达","modelType":"窄体","isStopOver":"N","fltArrTimeE":"2022-04-21 21:13","isFav":"0","flightArrtimePlan":"2022-04-21 21:23","flightStatusFlag":"5","flightArr":"JHG","fltProgress":"100","fltTotalTime":7200000,"isShare":"N","fltArrTimeS":"2022-04-21 21:00"}]},"securityCode":"0000"} String retStr = response.body().string(); JSONObject obj = JSONObject.fromObject(retStr); Map<String, Class<?>> classMap = new HashMap<>(); classMap.put("flights", Flights.class); FlightResponse flightResponse = (FlightResponse) JSONObject.toBean(obj,FlightResponse.class, classMap);
net.sf.ezmorph.bean.MorphDynaBean@3d92f1
net.sf.ezmorph.bean.MorphDynaBean@3d92f1
是 json-lib 中的一个内置对象,当对象缺省的时候,就用这个对象接收。你也可以用它,但是我们往往是需要返回我们自己的实体,或者自己的泛型集合。
net.sf.ezmorph.bean.MorphDynaBean@3d92f1的形成
下面是一个对象实体,然后answers
是一个List<SOAskAnswers>
public class SOAsk implements Serializable{
private static final long serialVersionUID = 1L;
/**回答集合*/
private List<SOAskAnswers> answers = new ArrayList<SOAskAnswers>();
/**分类*/
private String category;
/**分类名称*/
private String categoryName;
/**创建日期*/
private String date;
/**seo - 描述*/
private String description;
/**seo - 关键词*/
private String keywords;
/**来源 */
private String from ;
/**数据ID,url*/
private String id;
/**问题描述*/
private String question;
/**浏览次数*/
private long readCount = 0 ;
/**标题*/
private String title;
/**用户ID*/
private String userId;
/**用户名称*/
private String userName;
/**状态。0:没满意答案,1:有满意答案*/
private int status = 0;
//TODO getter & setter
}
JSON 反射对象的时候,集合对象就出现了net.sf.ezmorph.bean.MorphDynaBean@3d92f1
//查询返回一个JSON(map),然后反射回来对象,其中有一个属性就是集合。
List<SOAsk> list = new ArrayList<SOAsk>();
for (SearchHit searchHit : hits) {
Map<String, Object> source = searchHit.getSource();
JsonConfig config = new JsonConfig();
//设置对象class
config.setRootClass(SOAsk.class);
SOAsk entity = (SOAsk)JSONObject.toBean(JSONObject.fromObject(source) , config);
list.add(entity);
}
解决办法:
//查询返回一个JSON(map),然后反射回来对象,其中有一个属性就是集合。
List<SOAsk> list = new ArrayList<SOAsk>();
for (SearchHit searchHit : hits) {
Map<String, Object> source = searchHit.getSource();
JsonConfig config = new JsonConfig();
//设置对象class
config.setRootClass(SOAsk.class);
//键值对的设置对象Class
Map<String,Class<?>> classMap = new HashMap<String, Class<?>>();
//设置集合List<SOAskAnswers> answers = new ArrayList<SOAskAnswers>() 的泛型类型为SOAskAnswers
classMap.put("answers", SOAskAnswers.class);
//这里可以设置多个,如果当前对象里有很多的话 。。。
//设置进去
config.setClassMap(classMap);
SOAsk entity = (SOAsk)JSONObject.toBean(JSONObject.fromObject(source) , config);
list.add(entity);
}