java 如何使用Jackson将连接的JSON blob的String处理为String列表?

niwlg2el  于 2023-04-19  发布在  Java
关注(0)|答案(2)|浏览(109)

我有一个String,其中包含不同结构的串联JSON对象,我想将其转换为字符串列表。例如,给定以下输入:

{
  "foo": "bar"
}{
  "wibble": "wobble"
}

...我希望有一个List<String>对象输出,看起来像这样:

[{"foo":"bar"}, {"wibble":"wobble"}]

理想情况下,我不想自己实现JSON规范。我发现了一个使用Jackson的简单实现,如果我的初始字符串不包含额外的空格,它就可以工作:

public List<String> extractJsonBlobs(String json) throws IOException {
    if (json.length() == 0) return ImmutableList.of();

    ObjectMapper objectMapper = new ObjectMapper();
    JsonNode jsonNode = objectMapper.readValue(json, JsonNode.class);

    return new ImmutableList.Builder<String>()
            .add(jsonNode.toString())
            .addAll(extractJsonBlobs(
                    json.substring(jsonNode.toString().length())
            ))
            .build();
}
// this input works as described
String workingString = "{\"foo\":\"bar\"}{\"wibble\":\"wobble\"}";

// this input fails
String problemString = "{\n" +
        "  \"foo\": \"bar\"\n" +
        "}{\n" +
        "  \"wibble\": \"wobble\"\n" +
        "}";

问题是jsonNode.toString().length()总是给我可能的最小表示(在本例中第一个对象为13),而我需要的是连接的JSON对象的原始未处理字符串长度(在本例中第一个对象为18)。我如何获得“原始”字符串长度 * 或 * 以其他方式迭代这些JSON对象?谢谢!

8wigbo56

8wigbo561#

我的解决方案涉及使用解析器(而不是只使用ObjectMapper),但使用JsonNode并再次依赖其toString()行为来给予我一个JSON字符串表示:

public List<String> extractJsonBlobs(String json) throws IOException {
        JsonFactory factory = new JsonFactory(new ObjectMapper());
        JsonParser parser = factory.createParser(json);
        Iterator<JsonNode> messages = parser.readValuesAs(JsonNode.class);

        return Streams.stream(messages)
                .map(m -> m.toString())
                .collect(toList());
    }
polkgigr

polkgigr2#

这里有另一个解决方案:

public List<String> extractJsonBlobs(String json) {

        JsonMapper mapper = new JsonMapper();
        List<String> jsonBlobs = new ArrayList<>();

        MappingIterator<JsonNode> it = mapper.readerFor(JsonNode.class)
                .readValues(json)) {
            while (it.hasNextValue()) {
                jsonBlobs.add(it.nextValue().toString());
            }

        return jsonBlobs;
    }

如果数据不完整(例如,来自流),您可以尝试在JsonEOFException中捕获它,以便在缓冲区中预先添加丢失的数据:

public List<String> extractJsonBlobs(String json) {

        JsonMapper mapper = new JsonMapper();
        List<String> jsonBlobs = new ArrayList<>();

        int lastSuccessfulParseCharLocation = 0;

        try (MappingIterator<JsonNode> it = mapper.readerFor(JsonNode.class)
                .readValues(json)) {
            while (it.hasNextValue()) {
                jsonBlobs.add(it.nextValue().toString());
                lastSuccessfulParseCharLocation = (int) it.getCurrentLocation().getCharOffset();
            }

        } catch (JsonEOFException e) {
            charBuffer.position(lastSuccessfulParseCharLocation);
            Arrays.fill(prependChars, '\0');
            charBuffer.get(prependChars, 0, (charBuffer.length()));

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return jsonBlobs;
    }

对于上下文,charBuffer是CharBuffer,prependChars是char[]

相关问题