首页 > 解决方案 > 比较一个 JSON 有效负载是否包含另一个 JSON 有效负载

问题描述

我有 3 个JSON有效载荷ABC. 我需要确定有效载荷是否A包含Band C

注意:下面JSON的有效载荷只是示例,可以有不同的结构和值。

有效载荷A

{
  "id": "1",
  "search": {
    "name": "Testing",
    "age": "25",
    "school": "sacred heart"
  },
  "Address": {
    "street": "Abcedf",
    "road": "4th cross",
    "city": "bangalore"
  }
}

有效载荷B

{
  "id": "1",
  "search": {
    "name": "Testing"
  },
  "Address": {
    "street": "Abcedf",
    "road": "4th cross"
  }
}

有效载荷C

{
  "id": "1",
  "search": {
    "name": "Testing",
    "college": "global"
  },
  "Address": {
    "street": "Abcedf",
    "road": "4th cross"
  }
}

标签: javajsonjacksongsoncontains

解决方案


您可以利用JsonPointer来实现contains方法。当 object包含所有具有 object 的指针并且所有值都相同时,A.contains(B)方法返回。两个对象 (和) 是when和。根据定义:为每个.trueABABequalA.contains(B)B.contains(A)A.contains(A)trueA

简单的实现可能如下所示:

import com.fasterxml.jackson.core.JsonPointer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class JsonPointersApp {
    public static void main(String[] args) throws IOException {
        File aJsonFile = new File("./resource/a.json").getAbsoluteFile();
        File bJsonFile = new File("./resource/b.json").getAbsoluteFile();
        File cJsonFile = new File("./resource/c.json").getAbsoluteFile();

        ObjectMapper mapper = new ObjectMapper();
        JsonPayload payloadA = new JsonPayload(mapper.readTree(aJsonFile));
        JsonPayload payloadB = new JsonPayload(mapper.readTree(bJsonFile));
        JsonPayload payloadC = new JsonPayload(mapper.readTree(cJsonFile));
        System.out.println("JSON A:" + payloadA);
        System.out.println("JSON B:" + payloadB);
        System.out.println("JSON C:" + payloadC);
        System.out.println("A contains B:" + payloadA.contains(payloadB));
        System.out.println("A contains C:" + payloadA.contains(payloadC));
        System.out.println("B contains C:" + payloadB.contains(payloadC));
        System.out.println("C contains B:" + payloadC.contains(payloadB));
        System.out.println("A contains A:" + payloadA.contains(payloadA));
    }
}

class JsonPayload {

    private final JsonNode root;
    private final List<JsonPointer> pointers = new ArrayList<>();

    JsonPayload(JsonNode root) {
        this.root = Objects.requireNonNull(root);
        findPointers(this.root, "");
    }

    public boolean contains(JsonPayload other) {
        //If number of pointers are different, JSON payloads are also different
        if (this.pointers.size() < other.pointers.size()) {
            return false;
        }
        // If pointers are not the same
        if (!this.pointers.containsAll(other.pointers)) {
            return false;
        }
        // check values
        return other.pointers
                .stream()
                .allMatch(p -> this.root.at(p).equals(other.root.at(p)));
    }

    private void findPointers(JsonNode node, String path) {
        if (node.isObject()) {
            node.fields().forEachRemaining(entry -> findPointers(entry.getValue(), path + "/" + entry.getKey()));
        } else if (node.isArray()) {
            final int size = node.size();
            for (int i = 0; i < size; i++) {
                findPointers(node.get(i), path + "/" + i);
            }
        } else {
            pointers.add(JsonPointer.compile(path));
        }
    }

    @Override
    public String toString() {
        return pointers.toString();
    }
}

上面的代码打印:

JSON A:[/id, /search/name, /search/age, /search/school, /Address/street, /Address/road, /Address/city]
JSON B:[/id, /search/name, /Address/street, /Address/road]
JSON C:[/id, /search/name, /search/college, /Address/street, /Address/road]
A contains B:true
A contains C:false
B contains C:false
C contains B:true
A contains A:true

推荐阅读