You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何统计everit JSON Schema中定义的校验规则数量?

统计org.everit.json.schema中Schema对象的校验规则数量

针对org.everit.json.schema-1.12.1版本,推荐两种实现方式,覆盖不同场景需求:

方法一:基于SchemaVisitor实现(推荐,全面覆盖)

everit的Schema体系原生提供SchemaVisitor接口,用于遍历Schema的所有属性与子Schema,通过实现该接口可以精准统计各类校验规则,包括嵌套Schema的规则。

自定义规则统计Visitor

import org.everit.json.schema.*;
import java.util.HashMap;
import java.util.Map;

public class SchemaRuleCounter implements SchemaVisitor {
    private final Map<String, Integer> ruleCount = new HashMap<>();

    @Override
    public void visitStringSchema(StringSchema stringSchema) {
        countRule("minLength", stringSchema.getMinLength().isPresent());
        countRule("maxLength", stringSchema.getMaxLength().isPresent());
        countRule("pattern", stringSchema.getPattern().isPresent());
        countRule("format", stringSchema.getFormat().isPresent());
        visitCommonRules(stringSchema);
    }

    @Override
    public void visitNumberSchema(NumberSchema numberSchema) {
        countRule("minimum", numberSchema.getMinimum().isPresent());
        countRule("maximum", numberSchema.getMaximum().isPresent());
        countRule("exclusiveMinimum", numberSchema.isExclusiveMinimum());
        countRule("exclusiveMaximum", numberSchema.isExclusiveMaximum());
        countRule("multipleOf", numberSchema.getMultipleOf().isPresent());
        visitCommonRules(numberSchema);
    }

    @Override
    public void visitObjectSchema(ObjectSchema objectSchema) {
        countRule("required", !objectSchema.getRequiredProperties().isEmpty());
        countRule("properties", !objectSchema.getPropertySchemas().isEmpty());
        countRule("additionalProperties", objectSchema.getAdditionalPropertiesSchema().isPresent());
        countRule("minProperties", objectSchema.getMinProperties().isPresent());
        countRule("maxProperties", objectSchema.getMaxProperties().isPresent());
        // 递归统计子属性Schema
        objectSchema.getPropertySchemas().values().forEach(schema -> schema.accept(this));
        visitCommonRules(objectSchema);
    }

    @Override
    public void visitArraySchema(ArraySchema arraySchema) {
        countRule("minItems", arraySchema.getMinItems().isPresent());
        countRule("maxItems", arraySchema.getMaxItems().isPresent());
        countRule("uniqueItems", arraySchema.isUniqueItems());
        countRule("items", arraySchema.getItemSchema().isPresent());
        // 递归统计tuple类型的子Schema
        arraySchema.getItemSchemas().forEach(schema -> schema.accept(this));
        visitCommonRules(arraySchema);
    }

    @Override
    public void visitCombinedSchema(CombinedSchema combinedSchema) {
        countRule("allOf", !combinedSchema.getAllOfSchemas().isEmpty());
        countRule("anyOf", !combinedSchema.getAnyOfSchemas().isEmpty());
        countRule("oneOf", !combinedSchema.getOneOfSchemas().isEmpty());
        countRule("not", combinedSchema.getNotSchema().isPresent());
        // 递归统计组合子Schema
        combinedSchema.getAllOfSchemas().forEach(schema -> schema.accept(this));
        combinedSchema.getAnyOfSchemas().forEach(schema -> schema.accept(this));
        combinedSchema.getOneOfSchemas().forEach(schema -> schema.accept(this));
        combinedSchema.getNotSchema().ifPresent(schema -> schema.accept(this));
        visitCommonRules(combinedSchema);
    }

    @Override
    public void visitEnumSchema(EnumSchema enumSchema) {
        countRule("enum", !enumSchema.getPossibleValues().isEmpty());
        visitCommonRules(enumSchema);
    }

    // 处理所有Schema通用规则
    private void visitCommonRules(Schema schema) {
        countRule("title", schema.getTitle().isPresent());
        countRule("description", schema.getDescription().isPresent());
        countRule("default", schema.getDefaultValue().isPresent());
        countRule("readOnly", schema.isReadOnly());
        countRule("writeOnly", schema.isWriteOnly());
    }

    // 统计单个规则的出现次数
    private void countRule(String ruleName, boolean exists) {
        if (exists) {
            ruleCount.put(ruleName, ruleCount.getOrDefault(ruleName, 0) + 1);
        }
    }

    // 获取总规则数量
    public int getTotalRuleCount() {
        return ruleCount.values().stream().mapToInt(Integer::intValue).sum();
    }

    // 获取各规则的详细统计
    public Map<String, Integer> getRuleCountDetails() {
        return new HashMap<>(ruleCount);
    }

    // 以下为其他Schema类型的空实现,可按需扩展
    @Override public void visitBooleanSchema(BooleanSchema booleanSchema) { visitCommonRules(booleanSchema); }
    @Override public void visitNullSchema(NullSchema nullSchema) { visitCommonRules(nullSchema); }
}

使用方式

// 假设你已通过SchemaLoader加载好目标Schema对象
Schema loadedSchema = ...;

SchemaRuleCounter counter = new SchemaRuleCounter();
loadedSchema.accept(counter);

// 输出总规则数
System.out.println("总校验规则数量:" + counter.getTotalRuleCount());

// 输出各规则的明细统计
counter.getRuleCountDetails().forEach((rule, count) -> {
    System.out.printf("%s: %d%n", rule, count);
});

方法二:基于反射实现(适合简单场景)

如果仅需统计单一类型的Schema(如简单字符串、对象Schema),可以通过反射直接读取Schema的属性,判断是否为有效校验规则。

反射统计工具类

import org.everit.json.schema.Schema;
import java.lang.reflect.Field;
import java.util.Optional;

public class ReflectionRuleCounter {
    public static int countRules(Schema schema) {
        int count = 0;
        Class<?> clazz = schema.getClass();
        Field[] fields = clazz.getDeclaredFields();

        for (Field field : fields) {
            field.setAccessible(true);
            try {
                Object value = field.get(schema);
                // 判断是否为有效校验规则
                if (value instanceof Optional<?> && ((Optional<?>) value).isPresent()) {
                    count++;
                } else if (value instanceof Boolean && (Boolean) value) {
                    count++;
                } else if (value instanceof Iterable<?> && ((Iterable<?>) value).iterator().hasNext()) {
                    count++;
                }
                // 排除非校验规则的内部字段
                if ("schemaLocation".equals(field.getName()) || "id".equals(field.getName())) {
                    count--;
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return count;
    }
}

使用方式

Schema loadedSchema = ...;
int ruleCount = ReflectionRuleCounter.countRules(loadedSchema);
System.out.println("校验规则数量:" + ruleCount);

注意事项

  • 反射方式需要手动排除非校验规则字段,无法自动递归统计嵌套Schema的规则,仅适合简单场景。
  • 若使用了自定义Schema类型,需要在Visitor方法中补充对应的规则判断逻辑。

内容的提问来源于stack exchange,提问作者chandan Kr.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 12:27:26