Web Requests: JSON Input Validation
This feature is available in a current snapshot: 3.0-SNAPSHOT for Java 16 and up.
While ActiveWeb can process validations of simple classes as
described here,
often modern apps whether they are APIs or backends for a single page
app require a complex JSON structure. Such structures might be deeper
than a single level. In such cases, you can use the JavaLite JSON
capability that allows you to map a variable structure JSON object to a
class JSONBase
. The page JSON describes
basic JSONBase
features. However, the current page dives
deeper into JSON processing and validation in the context of a web
requests.
The class JSONBase
has two powerful features:
- It extends the
ValidationSupport
class that makes the entire Validation system available to subclasses. - It provides the JSON Deep Path feature.
In addition, the ActiveWeb does an implicit validation of any object
whose class extends JSONBase
.
Example JSON Processing
Let's say we have a web client (a browser, or an API client) post this JSON document in a web request:
{
"university": {
"students": [
{
"first_name": "Mary",
"last_name": "Smith"
},
{
"first_name": "Joe",
"last_name": "Shmoe"
}
]
}
}
A simple class for encapsulating this JSON object might look like this:
public class UniversityRequest extends JSONBase {
public UniversityRequest(Map jsonMap) {
super(jsonMap);
}
}
A controller would look like this:
public class UniversityController extends APIController {
@POST
public void saveStudents(UniversityRequest request) {
= request.getList("university.students");
JSONList students for (int i = 0; i < students.size(); i++) {
= students.getMap(i);
JSONMap student //... and so on...
}
}
}
By the time the action method saveStudents
is called,
the UniversityRequest
a JSON request was already parsed and
passed into the method.
JSON Validation
The class UniversityRequest
above extends from
JSONBase
, which provides various validations in the same
way the general Validations framework as well
as JSON Validations
operate.
Let's enhance the class UniversityRequest
with a single
validation:
public class UniversityRequest extends JSONBase {
public UniversityRequest(Map jsonMap) {
super(jsonMap);
validateList("university.students");
}
}
The last line in the constructor above will validate that the
structure of JSON will have a JSON Array (or Java List) at the path
"university.students"
. A controller would look a bit more
elaborate:
public class UniversityController extends APIController {
@POST
public void saveStudents(UniversityRequest request) {
if(request.isValid()){
= request.getList("university.students");
JSONList students for (int i = 0; i < students.size(); i++) {
= students.getMap(i);
JSONMap student //... and so on...
}
}else{
view("errors", request.errors());
render("/system/500");
}
}
}
As you can see, the ActiveWeb framework does most of the heavy lifting of parsing and verifying the incoming JSON requests.
JSON Validators
There many other validators in the package
org.javalite.json
ListValidator
Just as above, will validate that the structure at the path
"university.students"
is a list.
public class UniversityRequest extends JSONBase {
public PeopleRequest(Map jsonMap) {
super(jsonMap);
validateList("university.students");
}
}
MapValidator
Will validate that the structure at the path
"university"
is a map.
public class UniversityRequest extends JSONBase {
public PeopleRequest(Map jsonMap) {
super(jsonMap);
validateMap("university");
}
}
BooleanValidator
Will validate that the structure at the path
"university.active"
is a boolean.
public class UniversityRequest extends JSONBase {
public PeopleRequest(Map jsonMap) {
super(jsonMap);
validateBoolean("university.active");
}
}
another take on the boolean: will expect a pre-defined value:
public class UniversityRequest extends JSONBase {
public PeopleRequest(Map jsonMap) {
super(jsonMap);
validateBoolean("university.active", true);
}
}
Standard validators
Since the class JSONBase
ties into standard Validation framework, you can use any standard
validation in addition. Here is an example:
public class UniversityRequest extends JSONBase {
public PeopleRequest(Map jsonMap) {
super(jsonMap);
validateWith(new EmailValidator("university.address.email"));
}
}
as you can see, the twist that JSONBase
adds is a Deep
Path to a value in a JSON document.
Custom validator
If none of the existing validators work for you, you can implement a custom one:
public class PeopleRequest extends JSONBase {
public PeopleRequest(Map jsonMap) {
super(jsonMap);
validateWith(new JSONValidator() {
@Override
public void validateJSONBase(JSONBase jsonBase) {
boolean valid = false;
//this is where you can access the values of jsonBase for validation
if(!valid){
.addFailedValidator(this, "path.to.object");
jsonBasesetMessage("something did not pass validation");
}
}
});
}
}
As you can see, writing a custom validator is not complicated.
How to comment
The comment section below is to discuss documentation on this page.
If you have an issue, or discover bug, please follow instructions on the Support page