[英]Find the TYPE of any JSON element using its JSON Schema and Jackson Schema parser library in Java
我正在嘗試使用最高效和高性能的 memory 方法在 JSON 架構中查找任何元素的type
。 但是,在達到某個點后,我有點卡住並且沒有想法,所以希望在這里得到答案:
基本上,我有一個List: jsonPath
,它將由元素及其父元素組成,我需要從我擁有的Json Schema
中識別其類型。 為了解析Json Schema
,我正在使用Java Jackson Library
。 我能夠獲得所有元素並能夠找到它的類型,但在比較過程中,我有點困惑。
以下是我到目前為止的代碼:正如我們所看到的,我將jsonPath
作為"food", "Ingredients", "ingredient"
,這意味着我需要找到最后一個元素ingredient
的type
,而其他元素是它的父項。 該程序應返回type
為array
。 同樣,如果我在jsonPath array
中傳遞任何其他元素,例如只是food
或price
,那么它應該檢查相應的父母和他們的孩子,然后最終應該返回它的類型。 我使用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"
}
}
}
在嘗試了很多事情之后,我能夠做到。 添加代碼作為答案,因為它可以幫助將來嘗試實現類似目標的人:
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();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.