看起来您并没有绑定到 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 1的声明ValidatedJsonObjectRepresentingRequestOrResponse。
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: Discountblock 是一个命名块,由其他命名条目(对象或标量)组成。
Line 36: 第一个叫做valid_until
Line 35: 是必须的。
Line 34:如果它真的是一个字符串,则表示为一个字符串。如果不是,将返回一个错误。
Line 33: 最后,检查它没有过期。
Line 43: 第二个参数被调用promo_code。
Line 42: 也是必须的。
Line 41: 它必须包含字母和数字。
Line 40: 而且它不应该已经被赎回了。这个事实肯定会保存在我们的数据库中,因此 ...<br>
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
这个例子取自这里。在这里您可以找到一个完整的json 请求验证示例。