Генерация JSON с использованием JsonSchema в случае «oneOf» - PullRequest
0 голосов
/ 17 февраля 2020

Для моего проекта у меня есть несколько JSON схем, и мне нужно преобразовать их в JSON во время выполнения.

Для анализа схемы у меня есть 2 класса:

public class SchemaToTemplate {
    public static JsonObject convert(JsonObject schema) {
        if(isEmpty(schema)) return new JsonObject();
        if(!isNode(schema)) throw new RuntimeException("The given schema is malformed. Its root should be a valid JsonObject");
        if(!hasChildren(schema)) return new JsonObject();
        return parseParent(schema);
    }

    private static JsonObject parseParent(JsonObject schemaNode) {
        if(hasChildren(schemaNode)) {
            return parseParent(schemaNode, new JsonObject(), getChildrenNames(schemaNode));
        }
        return new JsonObject();
    }

    private static JsonObject parseChild(JsonObject schemaParent, JsonObject instanceParent, String key) {
        final JsonObject schemaChildNode = getChild(schemaParent, key);
        if(isEmpty(schemaChildNode)) return instanceParent;
        if(isNode(schemaChildNode)) {
            add(instanceParent, key, parseParent(schemaChildNode));
        }else{
            add(instanceParent, key, getValue(schemaChildNode));
        }
        return instanceParent;
    }

    private static JsonObject parseParent(JsonObject schemaParent, JsonObject instanceParent, List<String> childrenNames) {
        if(childrenNames.isEmpty()) {
            return instanceParent;
        }
        final String childName = childrenNames.remove(0);
        if(isSelector(childName)) {
            return parseSelector(schemaParent, instanceParent, childName);
        }
        final JsonObject newInstanceParent = parseChild(schemaParent, instanceParent, childName);
        return parseParent(schemaParent, newInstanceParent, childrenNames);
    }

    private static JsonObject parseSelector(JsonObject schemaParent, JsonObject instanceParent, String key) {
        final JsonArray array = schemaParent.getAsJsonArray(key);
        final JsonObject selector = new JsonObject();
        instanceParent.add("selector_" + key, selector);
        return parseArray(array, selector);
    }

    private static JsonObject parseArray(JsonArray schemaArray, JsonObject instanceNode) {
        if(schemaArray.size() == 0) {
            return instanceNode;
        }
        final JsonObject item = schemaArray.remove(0).getAsJsonObject();
        final JsonObject newInstanceNode = parseChild(item, instanceNode, getName(item));
        return parseArray(schemaArray, newInstanceNode);
    }

    //Util
    private static final String PROPERTIES = "properties";
    private static final String VALUE = "default";
    private static final String NAME = "title";
    private static final String TYPE = "type";
    private static final String TYPE_OBJECT = "object";
    private static final JsonObject EMPTY = new JsonObject();

    private static boolean isEmpty(JsonObject element) {
        return element.equals(EMPTY);
    }

    public static String getName(JsonObject element) {
        return SchemaUtil.getValue(element, NAME);
    }

    public static String getValue(JsonObject element) {
        return SchemaUtil.getValue(element, VALUE);
    }

    public static boolean isNode(JsonObject element) {
        return SchemaUtil.getValue(element, TYPE).equals(TYPE_OBJECT);
    }

    private static boolean hasChildren(JsonObject element) {
        return !isEmpty(getChildrenContainer(element));
    }

    public static List<String> getChildrenNames(JsonObject element) {
        return Lists.newArrayList(getChildrenContainer(element).keySet());
    }

    public static JsonObject getChild(JsonObject element, String key) {
        return getChildrenContainer(element).get(key).getAsJsonObject();
    }

    private static JsonObject getChildrenContainer(JsonObject element) {
        return getChildObject(element, PROPERTIES);
    }

    private static void add(JsonObject element, String key, JsonObject value){
        element.add(key, value);
    }

    private static void add(JsonObject element, String key, String value){
        element.addProperty(key, value);
    }
}

И класс утилит:


public class SchemaUtil {
    public static JsonObject getChildObject(JsonObject json, String key) {
        return json.get(key).getAsJsonObject();
    }

    public static String getValue(JsonObject json, String key) {
        return json.get(key).getAsJsonPrimitive().getAsString();
    }

    public static JsonObject replaceProperty(JsonObject json, String key, String value) {
        json.remove(key);
        json.addProperty(key, value);
        return json;
    }

    public static List<String> getKeys(JsonObject json) {
        return Lists.newArrayList(json.keySet());
    }

    public static boolean isSelector(String key) {
        return key.equals("oneOf") ||
                key.equals("anyOf") ||
                key.equals("allOf");
    }
}

Работает для всех схем, кроме тех, что , которые содержат "oneOf"

Fe

{
  "type": "object",
  "title": "Simple case",
  "properties": {
    "soaRS": {
      "$id": "/properties/simpleCase",
      "title": "Case Data",
      "type": "object",
      "oneOf": [
        {
          "title": "Simple Case 1",
          "type": "object",
          "properties": {
            "zah": {
              "$id": "/properties/data/properties/simpleCase/properties/parameter",
              "type": "string",
              "title": "Parameter 1",
              "default": "PA",
              "examples": [
                "PA"
              ]
            }
          }
        },
        {
          "title": "Simple case 2",
          "type": "object",
          "properties": {
            "zah": {
              "$id": "/properties/data/properties/simpleCase/properties/parameter3",
              "type": "string",
              "title": "Parameter 3",
              "default": "BBB",
              "examples": [
                "AI"
              ]
            }
          }
        }
      ]
    }
  }
}

Не могли бы вы указать мне направление, в котором я иду / делаю неправильно. Пытался бороться с разбором уже один день и до сих пор не знаю, как разобрать такой случай

Заранее спасибо!

...