public static JSONSchema of()

in core/src/main/java/com/alibaba/fastjson2/schema/JSONSchema.java [375:640]


    public static JSONSchema of(JSONObject input, JSONSchema parent) {
        if (input.size() == 1 && input.isArray("type")) {
            JSONArray types = input.getJSONArray("type");
            JSONSchema[] items = new JSONSchema[types.size()];
            for (int i = 0; i < types.size(); i++) {
                items[i] = JSONSchema.of(JSONObject.of("type", types.get(i)));
            }
            return new AnyOf(items);
        }

        Type type = Type.of(
                input.getString("type")
        );

        if (type == null) {
            Object[] enums = input.getObject("enum", Object[].class);
            if (enums != null) {
                boolean nonString = false;
                for (Object anEnum : enums) {
                    if (!(anEnum instanceof String)) {
                        nonString = true;
                        break;
                    }
                }
                if (!nonString) {
                    return new StringSchema(input);
                }

                return new EnumSchema(enums);
            }

            Object constValue = input.get("const");
            if (constValue instanceof String) {
                return new StringSchema(input);
            } else if (constValue instanceof Integer || constValue instanceof Long) {
                return new IntegerSchema(input);
            }

            if (input.size() == 1) {
                String ref = input.getString("$ref");
                if (ref != null && !ref.isEmpty()) {
                    if ("http://json-schema.org/draft-04/schema#".equals(ref)) {
                        JSONSchema schema = CACHE.get(ref);
                        if (schema == null) {
                            URL draf4Resource = JSONSchema.class.getClassLoader().getResource("schema/draft-04.json");
                            schema = JSONSchema.of(
                                    JSON.parseObject(draf4Resource),
                                    (JSONSchema) null
                            );
                            JSONSchema origin = CACHE.putIfAbsent(ref, schema);
                            if (origin != null) {
                                schema = origin;
                            }
                        }
                        return schema;
                    }

                    if ("#".equals(ref)) {
                        return parent;
                    }

                    Map<String, JSONSchema> definitions = null, defs = null, properties = null;
                    if (parent instanceof ObjectSchema) {
                        ObjectSchema objectSchema = (ObjectSchema) parent;

                        definitions = objectSchema.definitions;
                        defs = objectSchema.defs;
                        properties = objectSchema.properties;
                    } else if (parent instanceof ArraySchema) {
                        definitions = ((ArraySchema) parent).definitions;
                        defs = ((ArraySchema) parent).defs;
                    }

                    if (definitions != null) {
                        if (ref.startsWith("#/definitions/")) {
                            final int PREFIX_LEN = 14; // "#/definitions/".length();
                            String refName = ref.substring(PREFIX_LEN);
                            return definitions.get(refName);
                        }
                    }

                    if (defs != null) {
                        if (ref.startsWith("#/$defs/")) {
                            final int PREFIX_LEN = 8; // "#/$defs/".length();
                            String refName = ref.substring(PREFIX_LEN);
                            refName = URLDecoder.decode(refName);
                            JSONSchema refSchema = defs.get(refName);
                            if (refSchema == null) {
                                refSchema = new UnresolvedReference(refName);
                            }
                            return refSchema;
                        }
                    }

                    if (properties != null) {
                        if (ref.startsWith("#/properties/")) {
                            final int PREFIX_LEN = 13; // "#/properties/".length();
                            String refName = ref.substring(PREFIX_LEN);
                            return properties.get(refName);
                        }
                    }

                    if (ref.startsWith("#/prefixItems/") && parent instanceof ArraySchema) {
                        final int PREFIX_LEN = 14; // "#/properties/".length();
                        int index = Integer.parseInt(ref.substring(PREFIX_LEN));
                        return ((ArraySchema) parent).prefixItems[index];
                    }
                }

                Object exclusiveMaximum = input.get("exclusiveMaximum");
                Object exclusiveMinimum = input.get("exclusiveMinimum");
                if (exclusiveMaximum instanceof Integer
                        || exclusiveMinimum instanceof Integer
                        || exclusiveMaximum instanceof Long
                        || exclusiveMinimum instanceof Long) {
                    return new IntegerSchema(input);
                }

                if (exclusiveMaximum instanceof Number || exclusiveMinimum instanceof Number) {
                    return new NumberSchema(input);
                }
            }

            if (input.containsKey("properties")
                    || input.containsKey("dependentSchemas")
                    || input.containsKey("if")
                    || input.containsKey("required")
                    || input.containsKey("patternProperties")
                    || input.containsKey("additionalProperties")
                    || input.containsKey("minProperties")
                    || input.containsKey("maxProperties")
                    || input.containsKey("propertyNames")
                    || input.containsKey("$ref")
            ) {
                return new ObjectSchema(input, parent);
            }

            if (input.containsKey("maxItems")
                    || input.containsKey("minItems")
                    || input.containsKey("additionalItems")
                    || input.containsKey("items")
                    || input.containsKey("prefixItems")
                    || input.containsKey("uniqueItems")
                    || input.containsKey("maxContains")
                    || input.containsKey("minContains")
            ) {
                return new ArraySchema(input, parent);
            }

            if (input.containsKey("pattern")
                    || input.containsKey("format")
                    || input.containsKey("minLength")
                    || input.containsKey("maxLength")
            ) {
                return new StringSchema(input);
            }

            boolean allOf = input.containsKey("allOf");
            boolean anyOf = input.containsKey("anyOf");
            boolean oneOf = input.containsKey("oneOf");

            if (allOf || anyOf || oneOf) {
                int count = (allOf ? 1 : 0) + (anyOf ? 1 : 0) + (oneOf ? 1 : 0);
                if (count == 1) {
                    if (allOf) {
                        return new AllOf(input, parent);
                    }

                    if (anyOf) {
                        return new AnyOf(input, parent);
                    }

                    return new OneOf(input, parent);
                }
                JSONSchema[] items = new JSONSchema[count];
                int index = 0;
                if (allOf) {
                    items[index++] = new AllOf(input, parent);
                }
                if (anyOf) {
                    items[index++] = new AnyOf(input, parent);
                }
                if (oneOf) {
                    items[index++] = new OneOf(input, parent);
                }
                return new AllOf(items);
            }

            if (input.containsKey("not")) {
                return ofNot(input, null);
            }

            if (input.get("maximum") instanceof Number
                    || input.get("minimum") instanceof Number
                    || input.containsKey("multipleOf")
            ) {
                return new NumberSchema(input);
            }

            if (input.isEmpty()) {
                return Any.INSTANCE;
            }

            if (input.size() == 1) {
                Object propertyType = input.get("type");
                if (propertyType instanceof JSONArray) {
                    JSONArray array = (JSONArray) propertyType;
                    JSONSchema[] typeSchemas = new JSONSchema[array.size()];
                    for (int i = 0; i < array.size(); i++) {
                        Type itemType = Type.of(array.getString(i));
                        switch (itemType) {
                            case String:
                                typeSchemas[i] = new StringSchema(JSONObject.of("type", "string"));
                                break;
                            case Integer:
                                typeSchemas[i] = new IntegerSchema(JSONObject.of("type", "integer"));
                                break;
                            case Number:
                                typeSchemas[i] = new NumberSchema(JSONObject.of("type", "number"));
                                break;
                            case Boolean:
                                typeSchemas[i] = new BooleanSchema(JSONObject.of("type", "boolean"));
                                break;
                            case Null:
                                typeSchemas[i] = new NullSchema(JSONObject.of("type", "null"));
                                break;
                            case Object:
                                typeSchemas[i] = new ObjectSchema(JSONObject.of("type", "object"));
                                break;
                            case Array:
                                typeSchemas[i] = new ArraySchema(JSONObject.of("type", "array"), null);
                                break;
                            default:
                                throw new JSONSchemaValidException("not support type : " + itemType);
                        }
                    }
                    return new AnyOf(typeSchemas);
                }
            }

            if (input.getString("type") == null) {
                throw new JSONSchemaValidException("type required");
            } else {
                throw new JSONSchemaValidException("not support type : " + input.getString("type"));
            }
        }

        switch (type) {
            case String:
                return new StringSchema(input);
            case Integer:
                return new IntegerSchema(input);
            case Number:
                return new NumberSchema(input);
            case Boolean:
                return new BooleanSchema(input);
            case Null:
                return new NullSchema(input);
            case Object:
                return new ObjectSchema(input, parent);
            case Array:
                return new ArraySchema(input, parent);
            default:
                throw new JSONSchemaValidException("not support type : " + type);
        }
    }