0

是否有任何JSON库(阅读器)可以从数据源(例如,)进行字符串提取,“拉”式(逐条记录)InputStream,而无需将输入完全解析为对象?

例如,考虑JSON在一行中包含以下 3 条记录的文件:

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

这些可以分布在 3 行中,也JSON可以有多行记录,例如

{
  "a":"b"
}

需要的是一个 JSON 字符串“阅读器”,它可以根据需要逐条记录地迭代所有输入(类似于Iterator<String>对象)(即像StAX,而不是SAX)。例如,在上述有 3 条记录的情况下,输出将依次为

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

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

4

1 回答 1

1

是的,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>
于 2021-02-04T17:27:19.933 回答