JSON reader 将记录提取为 Java 字符串,无需解析

JSON reader to extract records as Java strings, without parsing

是否有任何 JSON 库 (reader) 可以从数据源(例如 InputStream), 没有将输入完全解析为对象?

例如,假设一个文件在一行中包含以下 3 JSON 条记录:

{"a":"b"}{"c":"d"}{"e":"f"}

这些可以分为 3 行,而且 JSON 可以有多行记录,例如

{
  "a":"b"
}

需要的是一个 JSON 字符串 "reader" 可以遍历所有输入(类似于 Iterator<String> 对象),逐个记录,按需(即像StAX, not SAX)。例如,在上面有 3 条记录的情况下,输出将依次为

reader.next() --> {"a":"b"}
reader.next() --> {"c":"d"}
reader.next() --> {"e":"f"}

一种技术是使用一个库来解析对象中的记录(例如,像 Jackson 中的 JsonNode 对象),然后从提取的对象中检索字符串版本,但用于读取只有这样才有不必要的解析开销。

是的,Jackson 可以使用 JsonParser 来解决这个问题。

例如,myfile.txt 具有以下内容:

{"a":"b"}
{
  "c":"d"
}{"e":"f"}

下面的程序会输出:

{"a":"b"}
{"c":"d"}
{"e":"f"}

代码:

public class Reader implements Closeable {
    JsonFactory jsonFactory = new JsonFactory();
    JsonParser jp;
    public Reader(InputStream inputStream) throws IOException {
        jp = jsonFactory.createParser(inputStream);
        jp.nextToken();
    }
    public String next() throws IOException {
        while (jp.currentToken() != JsonToken.START_OBJECT){
            jp.nextToken();
        }
        jp.nextToken(); //Next token will be the key
        if (jp.currentToken() == JsonToken.FIELD_NAME){
            StringBuilder sb = new StringBuilder().append("{\"")
                .append(jp.getCurrentName())
                .append("\":\"");
            jp.nextToken();//Next token will be the value. 
            sb.append(jp.getValueAsString())
                .append("\"}");
            return sb.toString();
        }
        return null;
    }
    public void close() throws IOException {
        jp.close();
    }
    public static void main(String args[]) throws IOException {
        Reader reader = new Reader(new FileInputStream("myfile.txt"));
        while (true){
            String token = reader.next();
            if (token == null){
                break;
            }
            System.out.println(token);
        }
    }
}

依赖关系

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-core</artifactId>
  <version>2.12.1</version>
</dependency>