I would like to validate incoming json object for correctness at the server side. Is there a standard / optimal way to do that? What is your approach of validation?
-
What server side language are you using? A lot will depend on that. – mattmc3 Feb 24 '11 at 04:14
3 Answers
My advice - deserialize the JSON and see if it breaks. For example, if you're using C# on the server side, you can use the newfangled DataContractJsonSerializer, or do it the old way with the JavaScriptSerializer which is arguably much simpler.
var serializer = new JavaScriptSerializer();
var result = serializer.Deserialize<Dictionary<string, object>>(jsonString);
EDIT: And now that it's come out that you're using Java, of course my C# example is not going to work for you, but the concept is the same. Stackoverflow already has some answers here: Convert a JSON string to object in Java ME?
-
Thanks for the response. I know the way to convert json to java object. I would want to do quick generic validation on it ( to check whether its valid ) before converting it into java object. – Harsha Hulageri Feb 24 '11 at 04:29
-
@Harsha Validating the JSON text would mean parsing it to some extent. Therefor, for correct json text (which should outnumber invalid json by a large factor in any decent application) you will end up doing double parsing. Is that really worth it? – rahulmohan Feb 24 '11 at 05:40
-
Many times you may want the validation to occur before the request hits the backend. In that case some sort of schema validation is in order. – TechTrip May 11 '12 at 09:37
Decode it with a JSON library. If it successfully decodes using a library that follows the specifications then it's valid.
- 740,318
- 145
- 1,296
- 1,325
-
1Yeah one of quickest way is to decode it into java object and see if it throws error while decoding. I want to do a generic validation on given json object without converting it into java object. I dont want to create java object just for validation. Any of your favorite json library / utility that would help me? – Harsha Hulageri Feb 24 '11 at 04:35
I can conclude from your comments that you first want to make sure that json object is valid, and if it is, you're ok with creating a java object. Whatever your argumentation is, validol library allows you to state however complex validation rules declaratively, which if successful, result in a java object.
Suppose you have an order registration request, which consists of several blocks, including payment. For brevity sake, I omit all the block except that one. Here is how this request looks like in this case:
{
"payment":{
"expires_at":"12/29",
"card_number":12345612341234
}
}
Here is a validation code:
/*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();
}
}
Let’s see what’s going on here, line by line:
Line 1 Declaration of ValidatedRegistrationRequest.
Line 6 Its constructor accepts not yet parsed json string. It might come from an incoming request, from received response, or from pretty much anywhere else.
Line 13: Validation starts when this method is invoked.
Line 16: The higher-level validation object is FastFail block. If the first argument is invalid, an error is returned right away.
Lines 17-19: json is checked whether it’s well-formed or not. If the latter, validation fails fast and returns a corresponding error.
Line 20: if json is well-formed, a closure is invoked, and json data is passed as its single argument.
Line 21: json data is validated. Its structure is an unnamed block of named blocks. It corresponds to a JSON Object.
Line 26: The first (and the only) block is called payment.
Line 25: It’s required.
Line 24: It must be a json object.
Line 23: If not, an error will be returned right away because it’s a FailFast object.
Line 29: Otherwise, a closure is invoked.
Line 30: Payment block is a named block consisting of other named entries – objects or scalars.
Line 36: The first one is called expires_at
Line 35: It’s required.
Line 34: And represented as a string, if possible. If not, an error will be returned.
Line 33: Finally, check that it’s not expired.
Line 43: Second parameter is called card_number.
Line 42: It’s required as well.
Line 41: It must satisfy Luhn algorithm.
Line 40: And it should not be blacklisted in our database, hence …
Line 46: … this.dbConnection parameter.
Line 49: If all previous validation checks are successful, an object of class Payment is created.
Line 53: Finally, RegistrationRequest is created and returned.
Here is how a calling code looks when validation is successful:
Result<RegistrationRequest> result = new ValidatedRegistrationRequest(jsonRequestString).result();
result.isSuccessful();
result.value().raw().payment().cardNumber(); // 12345612341234
You can find out more about the declarative validation approach, or proceed right away to quick start entry for more examples.
- 3,274
- 4
- 39
- 66