场景
- 开发
JSON
应用时,有时候需要从JSON
文件里读取配置数据到内存。当JSON
文件足够大时,如果先把文件读入内存再进行parse
会浪费不必要的大文件连续内存。甚至可能会导致OOM
, 这时候如果能像XML
文件那样可以以流的方式读取结构化JSON
数据,那么会节省很多内存。那么怎么做?
说明
-
开发
jfinal
框架的网站时,标配是fastjson-1.2.83
版本,也就是fastjson 1
的最高版本。如果不是特殊的用法,这个版本是够用且稳定的。 -
JSON
文件是UTF-8
格式,一般可以用它来做多语言文字存储格式。 常用的可以通过以下方式解析指定的JSON
格式。这种方式得先有内存的JSON
格式, 这种方式需要预先读取.json
文件所有内容到内存。
JSONObject object = JSONObject.parseObject(pageDataStr);
Object object = JSON.parse(pageDataStr);
- 还有就是
fastjson
提供了Stream API JSONReader
,来按流的方式读取指定部分json
对象,比如对象,数组,字符串,整数等。
JSONReader jr = new JSONReader(Reader)){
jr.startObject();
while(jr.hasNext()){
String key = jr.readString();
JSONObject value = (JSONObject) jr.readObject();
...
}
jr.endObject();
例子
- 以下例子读取文件的
json
格式并存储在一个大JSONObject里
。
try(InputStream is = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(isr);
JSONReader jr = new JSONReader(br)){
JSONObject object = new JSONObject();
// 明确知道`json`文件是以对象开始存储的。 {"name":"Peter"}
jr.startObject();
while(jr.hasNext()){
String key = jr.readString();
JSONObject value = (JSONObject) jr.readObject();
object.put(key,value);
}
jr.endObject();
data.put(localName,object);
return true;
} catch (FileNotFoundException e) {
log.error(e.getMessage());
} catch (IOException e) {
log.error(e.getMessage());
}
json file
{
"article": {
"home":"首页",
"support_center":"支持中心",
"sales_faqs":"销售常见问题",
"refund_faqs":"退款常见问题",
"product_faqs":"产品常见问题",
"online_tutorials":"在线教程",
"product_center":"产品中心"
}
}
参考
-
FastJson 读取超大json文件引起OOM问题排查与解决
-
fastjson 1
-
Quick Start CN · alibaba/fastjson Wiki
-
常见问题 · alibaba/fastjson Wiki
-
Stream api · alibaba/fastjson Wiki
-
JSON最佳实践