【发布时间】:2011-07-03 06:48:33
【问题描述】:
我想在服务器端验证传入的 json 对象的正确性。是否有标准/最佳方式来做到这一点?您的验证方法是什么?
【问题讨论】:
-
您使用什么服务器端语言?很大程度上取决于此。
标签: java json validation
我想在服务器端验证传入的 json 对象的正确性。是否有标准/最佳方式来做到这一点?您的验证方法是什么?
【问题讨论】:
标签: java json validation
我可以从您的 cmets 得出结论,您首先要确保 json 对象有效,如果有效,则可以创建 java 对象。无论您的论点是什么,validol 库都允许您以声明方式声明复杂的验证规则,如果成功,则会生成一个 java 对象。
假设您有一个订单注册请求,它由几个块组成,包括payment。为简洁起见,我省略了除此之外的所有块。在这种情况下,此请求如下所示:
{
"payment":{
"expires_at":"12/29",
"card_number":12345612341234
}
}
这是一个验证码:
/*1 */ public class ValidatedRegistrationRequest implements Validatable<RegistrationRequest>
{
private String jsonRequestString;
private Connection dbConnection;
/*6 */ public ValidatedRegistrationRequest(String jsonRequestString, Connection dbConnection)
{
this.jsonRequestString = jsonRequestString;
this.dbConnection = dbConnection;
}
@Override
/*13*/ public Result<RegistrationRequest> result() throws Exception
{
return
/*16*/ new FastFail<>(
/*17*/ new WellFormedJson(
/*18*/ new Unnamed<>(Either.right(new Present<>(this.jsonRequestString)))
),
/*20*/ requestJsonObject ->
/*21*/ new UnnamedBlocOfNameds<>(
/*22*/ List.of(
/*23*/ new FastFail<>(
/*24*/ new IsJsonObject(
/*25*/ new Required(
/*26*/ new IndexedValue("payment", requestJsonObject)
)
),
/*29*/ paymentJsonObject ->
/*30*/ new NamedBlocOfNameds<>(
/*31*/ "payment",
/*32*/ List.of(
/*33*/ new CardIsNotExpired(
/*34*/ new AsString(
/*35*/ new Required(
/*36*/ new IndexedValue("expires_at", paymentJsonObject)
)
)
),
/*40*/ new CardNumberIsNotBlacklisted(
/*41*/ new CardNumberSatisfiesLuhnAlgorithm(
/*42*/ new Required(
/*43*/ new IndexedValue("card_number", paymentJsonObject)
)
),
/*46*/ this.dbConnection
)
),
/*49*/ Payment.class
)
)
),
/*53*/ RegistrationRequest.class
)
)
.result();
}
}
让我们逐行看看这里发生了什么:
Line 1ValidatedRegistrationRequest 的声明。Line 6 其构造函数接受尚未解析的 json 字符串。它可能来自传入的请求、收到的响应或几乎任何其他地方。Line 13:调用此方法时开始验证。Line 16:更高级别的验证对象是@987654332 @ 堵塞。如果第一个参数无效,则立即返回错误。Lines 17-19: 检查 json 是否格式正确。如果是后者,验证会很快失败并返回相应的错误。Line 20: 如果 json 格式正确,则调用闭包,并将 json 数据作为其单个参数传递。Line 21: json数据得到验证。它的结构是命名块的未命名块。它对应一个 JSON 对象。Line 26:第一个(也是唯一的)块称为 payment。Line 25:它是必需的。Line 24:它必须是一个 json对象。Line 23:如果不是,将立即返回错误,因为它是FailFast 对象。Line 29:否则,将调用闭包。Line 30:付款块是由其他命名条目(对象或标量)组成的命名块。Line 36:第一个称为 expires_atLine 35:它是必需的。Line 34:并表示为字符串,如果可能的话。如果没有,则返回错误。Line 33:最后,检查它是否过期。Line 43:第二个参数称为card_number。Line 42:也是必需的.Line 41: 必须满足 Luhn 算法。Line 40: 并且不应该在我们的数据库中列入黑名单,因此...Line 46: ... this.dbConnection 参数。
@ 987654356@:如果之前的所有验证检查都成功,则创建Payment 类的对象。Line 53:最后,创建并返回RegistrationRequest。
验证成功后调用代码如下所示:
Result<RegistrationRequest> result = new ValidatedRegistrationRequest(jsonRequestString).result();
result.isSuccessful();
result.value().raw().payment().cardNumber(); // 12345612341234
您可以了解有关declarative validation 方法的更多信息,或立即前往quick start 条目以获取更多示例。
【讨论】:
我的建议 - 反序列化 JSON 并查看它是否损坏。例如,如果您在服务器端使用 C#,则可以使用新奇的 DataContractJsonSerializer,或者使用旧方法使用 JavaScriptSerializer,这可以说要简单得多。
var serializer = new JavaScriptSerializer();
var result = serializer.Deserialize<Dictionary<string, object>>(jsonString);
编辑:既然您使用的是 Java,那么我的 C# 示例当然不适用于您,但概念是相同的。 Stackoverflow 已经有了一些答案here: Convert a JSON string to object in Java ME?
【讨论】:
使用 JSON 库对其进行解码。如果它使用遵循规范的库成功解码,则它是有效的。
【讨论】: