I use sf.json library to map form data for incoming request in my web application in java.
Lets say the incoming request is http://localhost:8080/app/addProfile with
Often times json schema might seem like overkill. It's quite complicated and clumsy to my taste, and adding more rules makes things worse.
I think a way simpler, but still declarative approach taken in validol library could be a good alternative. The main point is binding business rules to data they apply to. Complex rules decorate more basic ones. And an entire validation tree represents a single functional declarative expression. Besides, this approach encourages you to put validation logic where it belongs to: in a specific user scenario.
Here is an example of what it could look like. Consider a schema to be validated:
{
"where":{
"building":1,
"street":"Red Square"
}
}
Validation logic reflects the structure of json schema. All the constraints are described right in the structure itself. All the mundane checks like json key existence are already taken care of.
Here it goes:
/*1 */ new FastFail<>(
/*2 */ new IsJsonObject(
/*3 */ new WellFormedJson(
/*4 */ new IndexedValue("where", jsonString)
)
),
/*7 */ whereJsonElement ->
/*8 */ new NamedBlocOfNameds<>(
/*9 */ "where",
/*10*/ List.of(
/*11*/ new AsString(
/*12*/ new Required(
/*13*/ new IndexedValue("street", whereJsonElement)
)
),
/*16*/ new AsInteger(
/*17*/ new Required(
/*18*/ new IndexedValue("building", whereJsonElement)
)
)
),
/*22*/ Where.class
)
)
.result();
It's a pity that stackoverflow doesn't support line numbers, but, anyways, here's what's going on line by line.
Line 1: The whole validation is a fast fail thing, the one returning an error if the first argument results in an error.
Line 4: The first argument is a declaration of a where block.
Line 3: It must be a well-formed json.
Line 2: Besides, it should be a json object.
Line 7: The second argument is a closure. It's first argument is a where json object.
Line 8: Here goes the named block of named elements.
Line 9: Its name is where.
Line 10: The second argument is a list of all elements.
Line 13: The first element is street.
Line 12: It's required.
Line 11: And should be represented as string.
Line 18: The second one is building.
Line 17: It's required as well.
Line 16: And should be represented as an integer.
Line 22: If all previous checks are successful, an Where object is created.
It's first argument is street, which must be a String; the second one is building, which must be an integer.
Take a look at quick-start section for more examples and line-by-line code analysis.