看起来您并没有绑定到 JSONSchema,尽管它似乎是您的默认选择。口味不同,但通常看起来更复杂。此外,就个人而言,我希望将数据和验证规则放在同一个地方。当在 java 代码而不是任何类型的配置文件中使用时,自定义验证器似乎更自然地适合。
这是这种方法的外观。比如说,您有以下 json 对象代表一些付款(无论是请求还是响应),但为简洁起见仅包含 discount 块:
{
"discount":{
"valid_until":"2032-05-04 00:00:00+07",
"promo_code":"VASYA1988"
}
}
验证码如下所示:
/*1 */ public class ValidatedJsonObjectRepresentingRequestOrResponse implements Validatable<JsonObjectRepresentingRequestOrResponse>
{
private String jsonString;
private Connection dbConnection;
/*6 */ public ValidatedJsonObjectRepresentingRequestOrResponse(String jsonString, Connection dbConnection)
{
this.jsonString = jsonString;
this.dbConnection = dbConnection;
}
@Override
/*13*/ public Result<JsonObjectRepresentingRequestOrResponse> result() throws Exception
{
return
/*16*/ new FastFail<>(
/*17*/ new WellFormedJson(
/*18*/ new Unnamed<>(Either.right(new Present<>(this.jsonRequestString)))
/*19*/ ),
/*20*/ requestJsonObject ->
/*21*/ new UnnamedBlocOfNameds<>(
List.of(
/*23*/ new FastFail<>(
/*24*/ new IsJsonObject(
/*25*/ new Required(
/*26*/ new IndexedValue("discount", requestJsonObject)
)
),
/*29*/ discountObject ->
/*30*/ new NamedBlocOfNameds<>(
/*31*/ "discount",
/*32*/ List.of(
/*33*/ new PromoCodeIsNotExpired(
/*34*/ new AsString(
/*35*/ new Required(
/*36*/ new IndexedValue("valid_until", discountObject)
)
)
),
/*40*/ new PromoCodeIsNotAlreadyRedeemed(
/*41*/ new PromoCodeContainsBothLettersAndDigits(
/*42*/ new Required(
/*43*/ new IndexedValue("promo_code", discountObject)
)
),
/*46*/ this.dbConnection
)
),
/*49*/ Discount.class
)
)
),
/*53*/ JsonObjectRepresentingRequestOrResponse.class
)
)
.result();
}
}
让我们逐行看看这里发生了什么:
Line 1ValidatedJsonObjectRepresentingRequestOrResponse 的声明。
Line 6 其构造函数接受原始 json 字符串。它可能是传入的请求或收到的响应,或者几乎是其他任何东西。
Line 13:在调用此方法时开始验证。
Lines 16:更高级别的验证对象是FastFail 块.如果第一个参数无效,则立即返回错误。
Lines 17-19: 检查 json 是否格式正确。如果是后者,验证会快速失败并返回相应的错误。
Line 20: 如果 json 格式正确,则调用闭包,并将 json 数据作为其单个参数传递。
Line 21: json数据得到验证。它的结构是命名块的未命名块。它对应一个 JSON 对象。
Line 26:第一个(也是唯一的)块称为 discount。
Line 25:它是必需的。
Line 24:它必须是一个 json对象。
Line 23:如果不是,将立即返回错误,因为它是FailFast 对象。
Line 29:否则,将调用闭包。
Line 30:@987654343 @ 块是由其他命名条目(对象或标量)组成的命名块。
Line 36:第一个称为 valid_until
Line 35:它是必需的。
Line 34:并表示作为一个字符串,如果它真的是一个字符串。如果没有,则返回错误。
Line 33:最后,检查它是否过期。
Line 43:第二个参数称为promo_code。
Line 42:也是必需的.
Line 41: 必须同时包含字母和数字。
Line 40: 并且它不应该已经被兑换了。这个事实肯定会保存在我们的数据库中,因此 ...
Line 46: ...this.dbConnection 参数。
Line 49: 如果所有先前的验证检查都成功,则创建一个 Discount 类的对象。Line 53: 最后,JsonObjectRepresentingRequestOrResponse 被创建并返回。
验证成功后调用代码如下所示:
Result<JsonObjectRepresentingRequestOrResponse> result = new ValidatedJsonObjectRepresentingRequestOrResponse(jsonRequestString).result();
result.isSuccessful();
result.value().raw().discount().promoCode(); // VASYA1988
这个例子取自here。在这里你可以找到一个成熟的json request validation example。