传统的解析JSON是要完全构建好一个完整的JSON文本内容然后通过JSON框架去解析反序列化,但是当JSON内容非常长,比如,一个JSON列表中存储有N个元组,而且非常长有上万个。这样在传输JSON文本内容的时候如何实现流式传输呢?方法当然是有的,在Solr的Xport代码中有就有这样一段代码,类名是:JSONTupleStream。
import java.io.IOException; import java.io.Reader; import java.util.List; import java.util.Map; import org.apache.solr.client.solrj.io.stream.SolrStream; import org.noggit.JSONParser; import org.noggit.ObjectBuilder; public class JSONTupleStream { private List<String> path; // future... for more general stream handling private Reader reader; private JSONParser parser; private boolean atDocs; public JSONTupleStream(Reader reader) { this.reader = reader; this.parser = new JSONParser(reader); } /** returns the next Tuple or null */ public Map<String,Object> next() throws IOException { if (!atDocs) { boolean found = advanceToDocs(); atDocs = true; if (!found) return null; } // advance past ARRAY_START (in the case that we just advanced to docs, or OBJECT_END left over from the last call. int event = parser.nextEvent(); if (event == JSONParser.ARRAY_END) return null; Object o = ObjectBuilder.getVal(parser); // right now, getVal will leave the last event read as OBJECT_END return (Map<String,Object>)o; } public void close() throws IOException { reader.close(); } private void expect(int parserEventType) throws IOException { int event = parser.nextEvent(); if (event != parserEventType) { throw new IOException("JSONTupleStream: expected " + JSONParser.getEventString(parserEventType) + " but got " + JSONParser.getEventString(event) ); } } private void expect(String mapKey) { } private boolean advanceToMapKey(String key, boolean deepSearch) throws IOException { for (;;) { int event = parser.nextEvent(); switch (event) { case JSONParser.STRING: if (key != null) { String val = parser.getString(); if (key.equals(val)) { return true; } else if("error".equals(val)) { handleError(); } } break; case JSONParser.OBJECT_END: return false; case JSONParser.OBJECT_START: if (deepSearch) { boolean found = advanceToMapKey(key, true); if (found) { return true; } } else { advanceToMapKey(null, false); } break; case JSONParser.ARRAY_START: skipArray(key, deepSearch); break; } } } private void handleError() throws IOException { for (;;) { int event = parser.nextEvent(); if(event == JSONParser.STRING) { String val = parser.getString(); if("msg".equals(val)) { event = parser.nextEvent(); if(event == JSONParser.STRING) { String msg = parser.getString(); if(msg != null) { throw new SolrStream.HandledException(msg); } } } } else if (event == JSONParser.OBJECT_END) { throw new IOException(""); } } } private void skipArray(String key, boolean deepSearch) throws IOException { for (;;) { int event = parser.nextEvent(); switch (event) { case JSONParser.OBJECT_START: advanceToMapKey(key, deepSearch); break; case JSONParser.ARRAY_START: skipArray(key, deepSearch); break; case JSONParser.ARRAY_END: return; } } } private boolean advanceToDocs() throws IOException { expect(JSONParser.OBJECT_START); advanceToMapKey("numFound", true); expect(JSONParser.LONG); // int event = parser.nextEvent(); //if (event == JSONParser.ARRAY_END) return null; System.out.println( ObjectBuilder.getVal(parser)); boolean found = advanceToMapKey("docs", true); expect(JSONParser.ARRAY_START); return found; } }
再写一段测脚本:
import java.io.StringReader; import java.util.Map; import com.dfire.tis.solrextend.core.JSONTupleStream; import junit.framework.TestCase; public class TestTupleStreamParser extends TestCase { public void test() throws Exception { StringReader reader = new StringReader("{\"responseHeader\": {\"status\": 0}, \"response\":{\"numFound\":" + 100 + ", \"docs\":[{name:'baisui'},{name:'xxxx'}]}"); JSONTupleStream tupleStream = new JSONTupleStream(reader); while (true) { Map<String, Object> tuple = tupleStream.next(); if (tuple != null) { System.out.println(tuple.get("name")); } else { break; } } } }
这样就可以做到,发送端不停得发送,客户端可以做到不断的去消费,这样做的好处是,当服务端客户端传输大量结构化数据的时候,可以避免首先要先开辟一个很大的内存空间,这样可以有效防止对内存溢出,同时,也可以有效提高系统吞吐率。
相关推荐
这是一个流式JSON解析器。 有关基于sax的简单版本,请参见以下要点: : MIT许可证(MIT)版权所有(c)2011-2012 Tim Caswell 特此免费授予获得此软件和相关文档文件(“软件”)副本的任何人无限制地处理软件的...
JSON :: Stream是基于有限状态机的JSON解析器,可为每个状态更改生成事件。 这允许将JSON文档流式传输到内存中,并将解析的对象图从内存中流式传输到其他进程。 这非常类似于XML SAX解析器,该解析器在解析期间生成...
Amp-streaming-json.zip,基于amp的流式json解析器。,amp是php的一个非阻塞并发框架。它提供事件循环、承诺和流,作为异步编程的基础。
流式CSV解析器,旨在实现最高速度以及与CSV酸测试套件的兼容性。 csv-parser可以以大约每秒90,000行的速度将CSV转换为JSON。 性能随所使用的数据而变化; 尝试bin/bench.js 基准测试您的数据。 csv-parser可以在...
gson-2.8.6.jar下载,gson是Google开发的一款优秀的Java JSON解析库。它可以将Java对象转换成JSON字符串,也可以将JSON字符串转换成...8. 高性能:gson通过流式API、缓存策略以及基于类型的Maass抽象序列化类来提高性能。
Saxerator是一种流式XML到哈希的解析器,旨在通过为您提供对文档的可管理块的可枚举访问权,来处理非常大的xml文件。 每个xml块都解析为类似JSON的Ruby Hash结构以供使用。 您可以通过3个简单的步骤来解析任何...
产品特点 与Swift 4的内置Codable功能集成 从JSON模式生成Swift值类型(草案5) JSON语言元素的简单不可变模型 高效的流式JSON解析器(可选) 基于类型的自定义对象的(反)序列化(无反射,无入侵) 不依赖...
还包括流式 SAX 启发的基于事件的 API。 stream-csv-as-json是的配套项目,旨在与其过滤器、流和通用基础设施一起使用。 可用组件: 流式 JSON。 它产生一个类似于 SAX 的令牌流。 可选地,它可以打包单个值。...
流式,与环境无关的JSON标记器。 基于 此标记生成器没有依赖项,并且与环境完全无关!因此它将在您的浏览器和节点中显示。当构建需要在任何环境下运行的应用程序时,这是一个不错的选择。 令牌生成器获取字符串流...
端点为ws://127.0.0.1:8080 / ws-rates 使用以下技术: Akka Http:Websockets和HttpClient Akka流:连接持久性数据库内容流和实时事件流Slick 3:基于Slick 3的简单DAO Spray Json:解析和查询Json