将 InputStream 中包含的 json diff 结果分离到 Java 中的映射中

separating json diff results contained inside of an InputStream into a map in Java

我将 Supplier 接收到一个方法中,该方法将根据根据 JsonDiff 所做的每个更改创建一个对象。供应商设置如下:

ObjectMapper mapper = new ObjectMapper();

// jsons to compare
String json1= "{}";
String json2= "{\"name\":\"Sean\", \"state\":\"Colorado\"}";

// convert jsons to JsonNode
JsonNode json1Node = mapper.readTree(json1);
JsonNode json2Node = mapper.readTree(json2);

// create Supplier<InputStream>
Supplier<InputStream> diffs = () ->
    new ByteArrayInputStream(JsonDiff.asJson(json1Node, json2Node).toString().getBytes());

产生的差异(在将其转换为 InputStream 之间)看起来像这样:

[{"op":"add", "path": "/name", "value": "Sean"}, {"op":"add", "path": "/State", "value": "Colorado"}]

当我收到这个供应商时,我希望能够将每个补丁单独成一个对象。该对象将简单地存储信息,设置如下:

private enum Op { 
 ADD, REPLACE, REMOVE
}

private Op op;
private String path;
private String value;

public Patch(Op op, String path, String value {
    this.op = op;
    this.path = path;
    this.value = value;
}

// getter methods

根据这个特定示例,我应该能够创建 2 个对象,1 个用于名称,1 个用于状态。

我的尝试是这样的:

private List<Patch> patches;
Map<String, String> map = new HashMap<>();
ObjectMapper mapper = new ObjectMapper();

try {
    // convert JSON string to Map
    map = mapper.readValue(diffs.get().toString(), new TypeReference<HashMap<String, String>>() {});

    // create patches
    for (String value : map.values()) {
        HashMap<String, String> result = mapper.readValue(value, HashMap.class);
        patches.add(new Patch(Patch.Op.valueOf(result.get("op").toUpperCase()), result.get("path"), result.get("value")));
    }
}catch (IOException e) {
    e.printStackTrace();
}

它在 "readValue" 行抛出以下异常:

com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'java': was expecting ('true', 'false' or 'null')
 at [Source: java.io.ByteArrayInputStream@1abf3bf; line: 1, column: 5]

似乎(至少这是我的解释)diff.get().toString() 调用没有返回任何远程接近 Json.

的东西

有人知道怎么做吗?

由于 jsondiff 的结果是一个数组,您可能无法将其解析为映射而不是列表。 此外,您不必调用 Supplier 输出的 toString() 方法。

这是一个使用最新版本的 jackson 的工作示例:

<dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.7.1-1</version>
        </dependency>
        <dependency>
            <groupId>com.github.fge</groupId>
            <artifactId>json-patch</artifactId>
            <version>1.9</version>
        </dependency>


public class Json {
    static class Patch {
        enum Op {
            ADD, REMOVE, REPLACE;
        };

        private final Op op;
        private final String path;
        private final String value;

        @JsonCreator
        public Patch(//
                @JsonProperty("op") String op, //
                @JsonProperty("path") String path, //
                @JsonProperty("value") String value) {
            this.op = Op.valueOf(op.toUpperCase());
            this.path = path;
            this.value = value;
        }

        @Override
        public String toString() {
            return "Patch [op=" + op + ", path=" + path + ", value=" + value + "]";
        }
    }

    public static void main(String[] args) throws Exception {

        // jsons to compare
        String json1 = "{}";
        String json2 = "{\"name\":\"Sean\", \"state\":\"Colorado\"}";

        // convert jsons to JsonNode
        JsonNode json1Node = mapper.readTree(json1);
        JsonNode json2Node = mapper.readTree(json2);

        // create Supplier<InputStream>
        final String strDiff = JsonDiff.asJson(json1Node, json2Node).toString();
        Supplier<InputStream> diffs = () -> new ByteArrayInputStream(strDiff.getBytes());

        MappingIterator<Patch> iterator = new ObjectMapper()//
                .readerFor(Patch.class) //
                .readValues(diffs.get());

        List<Patch> patches = new ArrayList<>();
        while (iterator.hasNext()) {
            patches.add(iterator.next());
        }
        System.out.println(patches);
    }
}

输出为:

[Patch [op=ADD, path=/name, value=Sean], Patch [op=ADD, path=/state, value=Colorado]]