`
mozhenghua
  • 浏览: 324475 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

基于流式解析JSON内容

阅读更多

        传统的解析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;
            }
        }
    }
}

 这样就可以做到,发送端不停得发送,客户端可以做到不断的去消费,这样做的好处是,当服务端客户端传输大量结构化数据的时候,可以避免首先要先开辟一个很大的内存空间,这样可以有效防止对内存溢出,同时,也可以有效提高系统吞吐率。

 

分享到:
评论

相关推荐

    jsonparse:用纯JavaScript编写的用于node.js的流式JSON解析器

    这是一个流式JSON解析器。 有关基于sax的简单版本,请参见以下要点: : MIT许可证(MIT)版权所有(c)2011-2012 Tim Caswell 特此免费授予获得此软件和相关文档文件(“软件”)副本的任何人无限制地处理软件的...

    java解析json所需jar包

    为了在Java中解析JSON,我们需要引入特定的库,这些库提供了API来帮助我们将JSON字符串转换为Java对象,反之亦然。标题提到的是“java解析json所需jar包”,这意味着我们将讨论Java中用于处理JSON的第三方库及其对应...

    XML通过sax解析JSON格式

    SAX(Simple API for XML)是一种基于事件驱动的XML解析器,适用于处理大型XML文档,因为它不会将整个文档加载到内存中。 标题中提到的"XML通过SAX解析为JSON格式"是指使用SAX解析器来读取XML文档,并将其转换成...

    json.rar_JSON_json解析_json解析的jar_解析json

    使用Gson,你可以通过以下方式解析JSON: ```java import com.google.gson.Gson; public class User { private String name; private int age; // getters and setters } String jsonString = "{\"name\":\...

    老罗android 解析json数据源码

    6. **性能优化**:对于大量JSON数据,可以考虑使用流式解析(如Gson的`JsonReader`)以减少内存消耗。另外,缓存已解析过的数据,避免重复解析,也能提升性能。 7. **数据绑定框架**:如Butter Knife、Data Binding...

    Android解析json速度对比

    在“Android解析json速度对比”的测试中,我们通常会设置一个标准的JSON数据集,然后使用这三个库进行反序列化操作,并记录每种库所花费的时间。测试方法可能包括以下步骤: 1. **数据准备**:创建一个包含大量键值...

    最简单最高效的Json解析

    2. **内存效率**:避免一次性加载大量数据,可以使用流式解析或分块处理大JSON文件,减少内存占用。 3. **性能优化**:选择高效的解析库,比如Java的Gson库或C++的RapidJSON库,它们提供了更快速的解析速度。 4. *...

    安卓Andriod源码——解析json_dome.zip

    4. **Android的内置解析器:JsonParser**:Android SDK还提供了一个`JsonParser`类,允许你以流式的方式解析JSON。这对于处理大体积的JSON数据特别有用,因为它不需要一次性加载整个JSON到内存中。 ```java ...

    java解析json文件所需jar包

    本压缩包包含了7个用于Java解析JSON文件的必备jar包,通过解压并将这些jar包添加到您的项目类路径中,您可以轻松实现JSON处理。 1. **Jackson库**: - Jackson是Java最流行的JSON处理库之一,由 FasterXML 组织...

    gson包解析json 数据

    7. **流式API**: Gson还提供了流式API,允许你逐行读取和写入JSON,这对于处理大型JSON文件或进行增量解析很有用。 8. **GsonBuilder**: `GsonBuilder`允许你配置Gson实例的行为,如设置日期格式、启用或禁用某些...

    Go-jstream是一个Go的流式JSON解析器和值提取库

    - 数据流处理:在网络传输或文件流中,实时解析JSON数据进行处理或存储。 - API接口:服务器接收大量JSON请求时,流式解析可以降低内存消耗并提高响应速度。 总的来说,Go-jstream是一个强大的工具,为Go开发者提供...

    Android 解析json_dome.zip源码资源下载

    当处理大量JSON数据时,应考虑性能优化,如使用流式解析,避免一次性加载整个JSON字符串到内存。 通过这个“Android解析json_dome.zip”源码,你可以深入理解各种JSON解析方法,并根据项目的实际需求选择合适的...

    Android解析json数据

    1. `org.json`库:Android SDK自带的JSON解析库,提供了`JSONObject`和`JSONArray`类,可以方便地解析JSON字符串并从中获取数据。 2. `com.google.code.gson`: Google提供的Gson库,可以将Java对象直接转换为JSON...

    QJson,qt解析json

    在使用QJson库时,需要注意的是,QJsonDocument在处理大型JSON文件时可能会消耗较多内存,因为它会一次性加载整个JSON内容。因此,对于大数据量的JSON,可能需要分块读取或使用流式解析的方式。 在实际项目中,...

    LitJson 解析json库

    JsonReader提供了一种逐字段解析JSON字符串的方法,而JsonWriter则允许我们逐步构建一个JSON结构。这两个类在处理大量或复杂JSON数据时特别有用,可以避免一次性加载整个JSON字符串到内存中。 在Unity3D环境中,...

    最好用的Json工具.exe

    例如,使用流式解析(Gson的`JsonReader`或Jackson的`JsonParser`)可以减少内存消耗。 8. JSON Schema:这是一种规范,用于定义JSON数据的结构和约束。配合使用,可以对JSON数据进行验证,确保其符合特定的要求。 ...

    C++ 解析Json

    它提供了流式解析和直接映射到C++对象的能力,使得JSON数据与C++对象的转换变得直观。 3. **JsonCpp**:这个库支持C++98和C++11,提供了一个简单的API来读写JSON。它可以将JSON数据解析为C++的对象,也可以将C++...

    C++Json解析开源库

    - **解析JSON**:你可以使用Json::Reader类将JSON字符串解析为Json::Value对象,如果解析成功,Reader会返回true,否则抛出异常。 - **构造JSON**:使用Json::Value对象,你可以构建JSON结构,并通过Json::...

    C#解析json文件的实现代码

    本文将深入探讨如何使用C#来解析JSON文件。 JSON是一种数据交换格式,其设计目标是为了便于人阅读和编写,同时也方便机器解析和生成。JSON语法基于JavaScript语法,但它是独立于语言的。JSON数据结构主要包括对象...

    json简单的解析

    要使用Jackson解析JSON,首先需要添加Jackson的依赖库到项目中。如果你的项目是Maven项目,可以在pom.xml文件中添加以下依赖: ```xml &lt;groupId&gt;com.fasterxml.jackson.core&lt;/groupId&gt; &lt;artifactId&gt;jackson-...

Global site tag (gtag.js) - Google Analytics