【问题标题】:Compare if one JSON payload contains another JSON payload比较一个 JSON 有效负载是否包含另一个 JSON 有效负载
【发布时间】:2021-01-19 11:59:37
【问题描述】:

我有 3 个JSON 有效载荷:ABC。我需要确定有效载荷A 是否包含BC

  • BA 进行比较时,我需要得到true 的结果。
  • CA 进行比较时,我需要结果为false 因为college 密钥在有效载荷A 中不存在。

注意: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"
  }
}

【问题讨论】:

    标签: java json jackson gson contains


    【解决方案1】:

    第一步是从您的 Json 创建 Java 对象。您可以使用 Gson、Jackson 或您选择的任何其他库。对于这个例子,我使用了 Gson。

    你的类定义

        private class JsonObject {
    
           String id;
           Map search;
           @SerializedName(value="Address")
           Map address;
    
           // getter and setter
        }
    

    解析对象(a、b 和 c 是您的 Json 字符串)

        Gson gson = new Gson();
        JsonObject objectA = gson.fromJson( a, JsonObject.class);
        JsonObject objectB = gson.fromJson( b, JsonObject.class);
        JsonObject objectC = gson.fromJson( c, JsonObject.class);
    

    对于实际比较,有很多方法可以完成您需要的。一种方法是实现自己的方法来比较对象

        private static boolean check( JsonObject firstObject, JsonObject secondObject ) {
        return firstObject.getAddress().entrySet().containsAll( secondObject.getAddress().entrySet()  )
                && firstObject.getSearch().entrySet().containsAll( secondObject.getSearch().entrySet() );
    }
    

    调用方法

        System.out.println( check ( objectA, objectB ) );
        System.out.println( check ( objectA, objectC ) );
    

    结果

    true
    false
    

    您当然可以创建自己的逻辑来比较对象内的地图。看看Java Collections FrameworkGuava 库,它提供了一些使用集合的便捷实用方法。

    【讨论】:

    • 您好,感谢您的 ans,但 json 是通用的,而不是静态的。上面的 jsons 只是一个例子。它实际上没有定义。对不起,我忘了在我的问题中提到这一点。我现在将其添加到我的问题中。
    【解决方案2】:

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

    简单的实现如下所示:

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-31
      相关资源
      最近更新 更多