Java环境下如何验证用户上传的JSON Schema合法性?
验证用户上传的内容是否为有效JSON Schema(Java + networknt/json-schema-validator)
嘿,刚好我对这个库很熟悉,完全可以实现你要的需求!核心思路其实很简单:用JSON Schema的「元Schema」来做验证——因为每一个合规的JSON Schema本身,都必须符合对应draft版本的元Schema规范。而普通的JSON数据(比如你示例里的car实例)肯定不满足元Schema的要求,这样就能轻松区分开。
下面是具体的实现步骤和代码示例:
核心原理
JSON Schema的官方定义里,每个draft版本都有对应的「元Schema」(比如你用的draft-04,元Schema标识是http://json-schema.org/draft-04/schema#)。这个元Schema的作用就是定义“什么样的JSON才算是合法的JSON Schema”。我们只要用这个元Schema作为验证器,去校验用户上传的内容,就能判断它是不是有效的Schema。
具体实现代码
1. 基础版本:验证指定draft版本(比如draft-04)
如果你只需要支持draft-04,可以直接写一个简单的验证方法:
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.networknt.schema.JsonSchema; import com.networknt.schema.JsonSchemaFactory; import com.networknt.schema.SpecVersion; import com.networknt.schema.ValidationMessage; import java.io.IOException; import java.util.Set; public class SchemaValidationUtil { private static final ObjectMapper objectMapper = new ObjectMapper(); public static boolean isValidDraft04Schema(String userUploadedContent) throws IOException { // 初始化对应draft-04的Schema工厂 JsonSchemaFactory factory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V4); // 加载draft-04的元Schema JsonSchema metaSchema = factory.getSchema("http://json-schema.org/draft-04/schema#"); // 解析用户上传的JSON内容 JsonNode userJson = objectMapper.readTree(userUploadedContent); // 执行验证,获取错误信息集合 Set<ValidationMessage> errors = metaSchema.validate(userJson); // 没有错误则说明是有效Schema return errors.isEmpty(); } // 测试一下 public static void main(String[] args) throws IOException { // 你的示例Schema,应该验证通过 String validSchema = "{ \"$schema\": \"http://json-schema.org/draft-04/schema#\", \"title\": \"car\", \"description\": \"representation of car\", \"type\": \"object\", \"required\": [ \"id\", \"make\", \"age\", \"model\", \"mileage\" ] }"; System.out.println("有效Schema测试:" + isValidDraft04Schema(validSchema)); // 输出true // 普通JSON数据,验证失败 String regularData = "{ \"id\": 1, \"make\": \"Toyota\", \"age\": 5 }"; System.out.println("普通数据测试:" + isValidDraft04Schema(regularData)); // 输出false } }
2. 进阶版本:自动识别draft版本
如果需要支持多个draft版本(比如draft-07、2019-09等),可以根据用户上传的Schema里的$schema字段自动匹配对应的元Schema:
public static boolean isValidJsonSchema(String userUploadedContent) throws IOException { JsonNode userJson = objectMapper.readTree(userUploadedContent); // 获取用户Schema中的$schema字段,确定版本 JsonNode schemaUrlNode = userJson.get("$schema"); if (schemaUrlNode == null || !schemaUrlNode.isTextual()) { // 如果没有指定$schema,默认用draft-04验证,或者提示用户补充 return isValidDraft04Schema(userUploadedContent); } String schemaUrl = schemaUrlNode.asText(); JsonSchemaFactory factory; // 根据$schema地址匹配对应的版本 if (schemaUrl.contains("draft-04")) { factory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V4); } else if (schemaUrl.contains("draft-07")) { factory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V7); } else if (schemaUrl.contains("draft-2019-09")) { factory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V201909); } else if (schemaUrl.contains("draft-2020-12")) { factory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V202012); } else { // 不支持的draft版本,返回验证失败 return false; } JsonSchema metaSchema = factory.getSchema(schemaUrl); Set<ValidationMessage> errors = metaSchema.validate(userJson); return errors.isEmpty(); }
注意事项
- 本地缓存元Schema:建议不要每次都从网络加载元Schema,把常用的draft版本元Schema保存到项目的
resources目录下,从本地文件加载,避免网络依赖和性能问题。比如:JsonSchema metaSchema = factory.getSchema(SchemaValidationUtil.class.getResourceAsStream("/draft-04-schema.json")); - 返回错误提示:如果验证失败,可以把
errors集合里的错误信息返回给用户,帮助他们修正Schema(比如errors.stream().map(ValidationMessage::getMessage).collect(Collectors.joining("\n")))。 - 处理无$schema的情况:如果用户上传的Schema没有
$schema字段,你可以选择默认用某个版本验证,或者直接返回错误要求用户指定,这样验证结果会更准确。
内容的提问来源于stack exchange,提问作者Benji
相关产品推荐
相关产品推荐

