代码之家  ›  专栏  ›  技术社区  ›  gil.fernandes

JSON路径:如何将URN引用转换为本地引用

  •  0
  • gil.fernandes  · 技术社区  · 6 年前

    同时使用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

        "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"
                  }
                }
              }
            }
          }
        }
    

    组织结构2pojo:jsonschema2pojo-maven-plugin:1.0.0-2

    1 回复  |  直到 6 年前
        1
  •  0
  •   gil.fernandes    6 年前

    也许有更好的方法来解决这个问题,但一个可能的解决办法是:

    使用递归方法转换 urn 将引用样式设置为本地引用:

    以下是使用Jackson库的递归方法:

    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);
        }
    }
    

    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"
              }
            }
          }
        }
      }
    }