java - JSON 路径:如何将 URN 引用转换为本地引用
问题描述
在使用 Maven 将 JSON 模式文件转换为 Java 类时,org.jsonschema2pojo:jsonschema2pojo-maven-plugin:1.0.0-alpha2
我收到与urn
无法解决的引用相关的错误。
这是一个示例错误消息:
[ERROR] Failed to execute goal org.jsonschema2pojo:jsonschema2pojo-maven-plugin:1.0.0-alpha2:generate (default) on project model-reservation: Execution default of goal org.jsonschema2pojo:jsonschema
2pojo-maven-plugin:1.0.0-alpha2:generate failed: Unrecognised URI, can't resolve this: urn:jsonschema:com:lumina:pnr:model:Reference: unknown protocol: urn -> [Help 1]
这是它与$ref
导致异常的元素一起引用的 JSON:
"remarkFields": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "object",
"id": "urn:jsonschema:com:lumina:pnr:model:FileFinishingField",
"properties": {
"lineNumber": {
"type": "integer"
},
"name": {
"type": "string"
},
"value": {
"type": "string"
},
"references": {
"type": "array",
"items": {
"type": "object",
"$ref": "urn:jsonschema:com:lumina:pnr:model:Reference"
}
}
}
}
}
}
如何将这些转换为 Java 中的本地引用并使用转换输出成功地将我的代码转换为使用org.jsonschema2pojo:jsonschema2pojo-maven-plugin:1.0.0-alpha2
Maven 插件的 Java 类?
解决方案
可能有更好的方法来解决这个问题,但一种可能的解决方案是:
使用递归方法将urn
样式引用转换为本地引用:
这是使用杰克逊库的递归方法:
private static final String ITEMS = "items";
private static final String ID = "id";
private static final String PROPERTIES = "properties";
private static final String ADDITIONAL_PROPERTIES = "additionalProperties";
private static final String REF = "$ref";
private static void parseReferences(JsonNode jsonNode, String path) {
if (jsonNode.has(ID)) {
typeMap.put(jsonNode.get(ID).asText(), path);
final JsonNode properties = jsonNode.get(PROPERTIES);
final Iterator<Map.Entry<String, JsonNode>> fields = properties.fields();
path += "/" + PROPERTIES;
while (fields.hasNext()) {
Map.Entry<String, JsonNode> entry = fields.next();
parseReferences(entry.getValue(), path + "/" + entry.getKey());
}
} else if (jsonNode.has(ITEMS)) {
final JsonNode item = jsonNode.get(ITEMS);
parseReferences(item, path + "/" + ITEMS);
} else if (jsonNode.has(REF)) {
ObjectNode objectNode = (ObjectNode) jsonNode;
objectNode.set(REF, new TextNode(typeMap.get(jsonNode.get(REF).asText())));
} else if (jsonNode.has(ADDITIONAL_PROPERTIES)) {
JsonNode additionalProperties = jsonNode.get(ADDITIONAL_PROPERTIES);
parseReferences(additionalProperties, path + "/" + ADDITIONAL_PROPERTIES);
}
}
这就是我在实例化 JAXB 解析器后调用此方法的方式:
private static void writeSchemaToFile(ObjectMapper jaxbObjectMapper, String origPath, String path) throws Exception {
InputStream resourceAsStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(origPath);
try (Reader r = new InputStreamReader(resourceAsStream, "UTF-8")) {
JsonNode root = jaxbObjectMapper.readTree(r);
parseReferences(root, "#");
String changedJson = jaxbObjectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(root);
final Path targetPath = Paths.get(path);
if (!Files.exists(targetPath)) {
Path parent = targetPath.getParent();
if (parent != null) {
Files.createDirectories(parent);
}
}
try (Writer writer = Files.newBufferedWriter(targetPath, Charset.forName("UTF-8"), StandardOpenOption.CREATE)) {
writer.write(changedJson);
}
}
}
如果调用此方法,它会将问题中指定的 JSON 转换为:
"remarkFields" : {
"type" : "object",
"additionalProperties" : {
"type" : "array",
"items" : {
"type" : "object",
"id" : "urn:jsonschema:com:lumina:pnr:model:FileFinishingField",
"properties" : {
"lineNumber" : {
"type" : "integer"
},
"name" : {
"type" : "string"
},
"value" : {
"type" : "string"
},
"references" : {
"type" : "array",
"items" : {
"type" : "object",
"$ref" : "#/properties/passengers/items/properties/reference"
}
}
}
}
}
}
推荐阅读
- python - 异步 IO 协程如何执行?
- c# - OpenQA.Selenium.ElementNotInteractableException:元素不可交互
- xamarin - 添加 MvvmCross.Plugins.Fingerprint 包 2.1.3 后 Xamarin Android 构建错误
- react-native - 如何通过按下 React Native 中的按钮来触发钩子?
- google-cloud-platform - 使用 Deployment Manager 在 BigQuery 中创建“外部表”时出现“403 Permission denied while getting Drive credentials”
- virtualhost - 使用 ngrok 公开一个虚拟主机
- sql-server-2016 - 将数据从 ODBC 导入 SQL Server 并使其生效
- jenkins - Jenkins Pipeline:批量调用中的参数
- oracle - 您可以使用 regexp_replace 从一个字符串中替换多个模式匹配项吗?
- javascript - Logic App/JavaScript - 为每个 JSON 对象分配一个随机密码