如何统计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.
相关产品推荐
相关产品推荐

