读取JSON到对象:java.lang.OutOfMemoryError:Java堆空间

时间:2019-02-18 15:28:37

标签: java java-8

我有这样的JSON:

{
field1: "asd",
theBigField: "bigggg300mb",
field2: "tyu"
}

我在方法输入参数上输入的是InputStream。我无法在JVM上增加内存,以便它可以接受该消息。我也无法执行return new ObjectMapper().readValue(bytes, MyModel.class),因为我没有足够的内存来根据此消息创建对象。我想做的是从消息中提取field1和field2并根据某些规则对其进行验证。

在方法开始处有InputStream。从中得到字节数组。如何提取field1field2

我正在使用Java8,可以使用流行的开源和轻量级库。也许可以通过编程方式以其他方式完成?

我要避免的是不要将整个消息读入内存,因此应该采用某种迭代方法。

1 个答案:

答案 0 :(得分:0)

我的第一个尝试是用MyClass::theBigField注释@JsonIgnore(如果使用Jackson / ObjectMapper)。不确定是否可以。

作为最后的选择,如果输入结构是固定的并且您事先知道,则可以尝试手动解析流。像这样:

    private static void parseMyJson(InputStream stream) throws IOException {
          StringBuffer[] fields = new StringBuffer[] { new StringBuffer(), null, new StringBuffer() };
          int fieldNum = 0;
          boolean readingFieldValue = false;
          int read = 0;
          while ((read = stream.read()) != -1) {
            char readChar = (char) read;
            if (readChar == '"') {
               fieldNum += readingFieldValue ? 0 : 1;
               readingFieldValue = !readingFieldValue;
            } else if (readingFieldValue && fieldNum != 2) {
               fields[fieldNum-1].append(readChar);
            }
          }
          System.out.println(fields[0].toString());
          System.out.println(fields[2].toString());
    }

上面的代码是一个非常原始且效率低下的解析器(您可能需要一些更高级的解析器),但要点是,您仅在内存中分配了一部分读取字符,如果它们与您的字段不对应,则将其丢弃有兴趣。