【问题标题】:Find the TYPE of any JSON element using its JSON Schema and Jackson Schema parser library in Java使用 Java 中的 JSON Schema 和 Jackson Schema 解析器库查找任何 JSON 元素的 TYPE
【发布时间】:2021-07-06 02:26:24
【问题描述】:

我正在尝试使用最节省内存和高性能的方法来查找 JSON Schema 中任何元素的 type。但是,在达到某个点后,我有点卡住并且没有想法,所以希望在这里得到答案:

基本上,我有一个List: jsonPath,它将由元素及其父元素组成,我需要从我拥有的Json Schema 中识别其类型。为了解析Json Schema,我使用Java Jackson Library。我能够获取所有元素并能够找到它的类型,但在比较过程中,我有点困惑。

以下是我目前的代码: 正如我们所看到的,我将jsonPath 设为"food", "Ingredients", "ingredient",这意味着我需要找到最后一个元素ingredienttype,而其他元素是它的父母。该程序应将type 作为array 返回。同样,如果我在jsonPath array 中传递任何其他元素,例如foodprice,那么它应该检查相应的父母和他们的孩子,然后最终应该返回它的类型。我使用Stack elements 仅供参考,您可以忽略它。

我可以尝试在每个阶段添加多个if 条件并获取元素类型。但是,我试图找到一种简单且更好的方法,而不是使用复杂的嵌套 if。应该可以以一种非常简单的方式完成,但目前对我来说没有任何点击。

 public class JsonElementLocator {

     private final JsonNode outerNode;
     private static JsonElementLocator _instance;

     // Default constructor to get the content and store in the root
     private JsonElementLocator() throws IOException {
         final ObjectMapper mapper = new ObjectMapper();
         final JsonNode root = mapper.readTree(JsonElementLocator.class.getClassLoader().getResource("testJSON.json"));
         outerNode = root.path("definitions");
     }

     // Method to create a Object instance of current class
     private static synchronized JsonElementLocator getInstance() throws IOException {
         if (_instance == null) {
             _instance = new JsonElementLocator();
         }
         return _instance;
     }

     // Method called by other application to get the element Type
     public static Optional < String > locate(List < String > elementPath) throws IOException {

         JsonElementLocator cl = getInstance();
         JsonNode rootNode = cl.outerNode;
         recurse(rootNode, new Stack < String > ());
         return Optional.empty();
     }

     // Method called recursively to get the element Type from JSON Schema
     private static Optional < String > recurse(JsonNode rootNode, Stack < String > elements) {

         // Loop through each Object in Root Node
         for (JsonNode childNode: rootNode) {

             // Check if childNode is of Object type
             if (childNode.path("type").toString().contains("object")) {

                 elements.push(childNode.get("title").toString());

                 // Call recurse method for the subsequent objects
                 recurse(childNode.path("properties"), elements);

                 elements.pop();

             } else if (childNode.path("type").toString().contains("array")) {
                 // Check if childNode is of Array type and call its elements

                 for (JsonNode ccNode: childNode.path("items")) {
                     final String def = ccNode.toString().contains("definitions") ? ccNode.toString().replace("\"", "").replaceAll("#/definitions/",
                         "") : null;

                     // Find the element from the root
                     if (def != null) {
                         final JsonNode defInfo = _instance.outerNode.get(def);

                         // Call recurse method for definition elements
                         recurse(defInfo.path("properties"), elements);
                     }

                 }

             } else {

                 System.out.println(String.join("/", elements));
                 // Check if childNode is of normal type
             }
         }
         return Optional.empty();
     }

     public static void main(String[] args) throws IOException {
         List < String > jsonPath = new ArrayList < String > (List.of("food", "Ingredients", "ingredient"));
         locate(jsonPath);
     }

 }

以下是我要解析的完整 Json Schema

{
    "$schema": "http://json-schema.org/draft-06/schema#",
    "$ref": "#/definitions/Welcome2",
    "definitions": {
        "Welcome2": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
                "hotelName": {
                    "type": "string"
                },
                "food": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/Food"
                    }
                }
            },
            "required": [
                "food",
                "hotelName"
            ],
            "title": "Welcome2"
        },
        "Food": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
                "name": {
                    "type": "string"
                },
                "price": {
                    "type": "string"
                },
                "description": {
                    "type": "string"
                },
                "calories": {
                    "type": "string",
                    "format": "integer"
                },
                "ingredients": {
                    "$ref": "#/definitions/Ingredients"
                }
            },
            "required": [
                "calories",
                "description",
                "ingredients",
                "name",
                "price"
            ],
            "title": "Food"
        },
        "Ingredients": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
                "ingredient": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                }
            },
            "required": [
                "ingredient"
            ],
            "title": "Ingredients"
        }
    }
}

【问题讨论】:

    标签: java json jackson jsonschema jsonnode


    【解决方案1】:

    在尝试了很多事情之后,我能够做到。添加代码作为答案,因为它可以帮助将来尝试实现类似目标的人:

    import java.io.IOException;
    import java.util.List;
    import java.util.Optional;
    import java.util.Stack;
    
    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    public class TypeLocator {
    
        private final JsonNode outerNode;
        private static TypeLocator _instance;
        private final JsonNode root;
    
        // Default constructor to get the content and store in the root
        private TypeLocator() throws IOException {
            // Create the jackson instance and get the JSON Schema Information
            final ObjectMapper mapper = new ObjectMapper();
            root = mapper.readTree(TypeLocator.class.getClassLoader().getResource("JSON-Schema.json"));
            outerNode = root.path("definitions");
        }
    
        // Method to create a Object instance of current class
        private static synchronized TypeLocator getInstance() throws IOException {
            if (_instance == null) {
                _instance = new TypeLocator();
            }
            return _instance;
        }
    
        // Method called by other application to get the element Type
        public static Optional<String> locate(List<String> elementPath) throws IOException {
    
    
            // Get the JSON Schema information
            TypeLocator cl = getInstance();
            JsonNode rootNode = cl.outerNode;
    
            // Check if there are element and obtain the event type info
            final String eventType = elementPath.get(0).substring(0, 1).toLowerCase() + elementPath.get(0).substring(1);
            final JsonNode eventInfo = rootNode.get(eventType);
            elementPath.remove(0);
            if (elementPath.size() > 0) {
    
                // Loop through elements in particular event Type and get type
                for (JsonNode allOf : eventInfo) {
                    for (JsonNode allElements : allOf) {
                        Optional<String> type = recurse(allElements, new Stack<String>(), elementPath);
                        if (type.isPresent()) {
                            return type;
                        }
                    }
                }
            }
            return Optional.empty();
    
        }
    
        private static Optional<String> recurse(JsonNode node, Stack<String> elements, List<String> elementPath) {
    
            // Check if its Reference type
            if (node.get("$ref") != null) {
                // Check if the element has reference to other definition
                final String ref = node.toString().contains("definitions") ? node.get("$ref").toString().replace("\"", "").replaceAll("#/definitions/",
                                    "") : null;
    
                // Check if the Reference is null
                if (ref != null) {
                    final JsonNode refElements = _instance.outerNode.get(ref);
                    return recurse(refElements, elements, elementPath);
                }
            } else if (node.get("items") != null && elementPath.size() > 0) {
                // Check if the element has Array type with items
                final String ref = node.get("items").toString().contains("definitions") ? node.get("items").get("$ref").toString().replace("\"", "")
                                    .replaceAll("#/definitions/", "") : null;
                if (elementPath.size() > 0 && elementPath.get(0).equals(ref)) {
                    elementPath.remove(0);
                    final JsonNode refElements = _instance.outerNode.get(ref);
                    return recurse(refElements, elements, elementPath);
                }
            } else if (node.get("properties") != null && elementPath.size() > 0) {
                // Check if the element has properties if no recurse through properties
                final JsonNode prop = node.get("properties");
    
                if (elementPath.size() > 0 && prop.get(elementPath.get(0)) != null) {
                    final JsonNode elementInfo = prop.path(elementPath.get(0));
                    elementPath.remove(0);
                    return recurse(elementInfo, elements, elementPath);
                }
            } else if (node.path("type") != null && elementPath.size() == 0) {
                // If the element has type then return the final Type
                return Optional.of(node.get("type").toString());
            } else {
                // If the element is not found then directly check
            }
            return Optional.empty();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-03-14
      • 1970-01-01
      • 1970-01-01
      • 2014-11-13
      • 2021-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多