How to validate a json is a correct representation of a class's object?
How to validate a json is a correct representation of a class's object?
Use JSON schema validator by newtonsoft , more details here
public class JsonSchemaController : ApiController
{
[HttpPost]
[Route("api/jsonschema/validate")]
public ValidateResponse Valiate(ValidateRequest request)
{
// load schema
JSchema schema = JSchema.Parse(request.Schema);
JToken json = JToken.Parse(request.Json);
// validate json
IList<ValidationError> errors;
bool valid = json.IsValid(schema, out errors);
// return error messages and line info to the browser
return new ValidateResponse
{
Valid = valid,
Errors = errors
};
}
}
public class ValidateRequest
{
public string Json { get; set; }
public string Schema { get; set; }
}
public class ValidateResponse
{
public bool Valid { get; set; }
public IList<ValidationError> Errors { get; set; }
}
1. Overview
When working with raw JSON values in Java, sometimes there is a need to check whether it is valid or not. There are several libraries that can help us with this: Gson, JSON API, and Jackson. Each tool has its own advantages and limitations.
In this tutorial, we’ll implement JSON String validation using each of them and take a closer look at the main differences between the approaches with practical examples.
2. Validation with JSON API
The most lightweight and simple library is the JSON API.
The common approach for checking if a String is a valid JSON is exception handling. Consequently, we delegate JSON parsing and handle the specific type of error in case of incorrect value or assume that value is correct if no exception occurred.
2.1. Maven Dependency
First of all, we need to include the json dependency in our pom.xml:
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20211205</version>
</dependency>Copy
2.2. Validating with JSONObject
Firstly, to check if the String is JSON, we will try to create a JSONObject. Further, in case of a non-valid value, we will get a JSONException:
public boolean isValid(String json) {
try {
new JSONObject(json);
} catch (JSONException e) {
return false;
}
return true;
}Copy
Let’s try it with a simple example:
String json = "{\"email\": \"example@com\", \"name\": \"John\"}";
assertTrue(validator.isValid(json));Copy
String json = "Invalid_Json";
assertFalse(validator.isValid(json));Copy
However, the disadvantage of this approach is that the String can be only an object but not an array using JSONObject.
For instance, let’s see how it works with an array:
String json = "[{\"email\": \"example@com\", \"name\": \"John\"}]";
assertFalse(validator.isValid(json));Copy
2.3. Validating with JSONArray
In order to validate regardless of whether the String is an object or an array, we need to add an additional condition if the JSONObject creation fails. Similarly, the JSONArray will throw a JSONException if the String is not fit for the JSON array as well:
public boolean isValid(String json) {
try {
new JSONObject(json);
} catch (JSONException e) {
try {
new JSONArray(json);
} catch (JSONException ne) {
return false;
}
}
return true;
}Copy
As a result, we can validate any value:
String json = "[{\"email\": \"example@com\", \"name\": \"John\"}]";
assertTrue(validator.isValid(json));Copy
3. Validation with Jackson
Similarly, the Jackson library provides a way to validate JSON based on Exception handling. It is a more complex tool with many types of parsing strategies. However, it’s much easier to use.
3.1. Maven Dependency
Let’s add the jackson-databind Maven dependency:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.0</version>
</dependency>Copy
3.2. Validating with ObjectMapper
We use the readTree() method to read the entire JSON and get a JacksonException if the syntax is incorrect.
In other words, we don’t need to provide additional checks. It works for both objects and arrays:
ObjectMapper mapper = new ObjectMapper()
.enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)
.build()
public boolean isValid(String json) {
try {
mapper.readTree(json);
} catch (JacksonException e) {
return false;
}
return true;
}Copy
Let’s see how we can use this with examples:
String json = "{\"email\": \"example@com\", \"name\": \"John\"}";
assertTrue(validator.isValid(json));
String json = "[{\"email\": \"example@com\", \"name\": \"John\"}]";
assertTrue(validator.isValid(json));
String json = "Invalid_Json";
assertFalse(validator.isValid(json));Copy
Note that we’ve also enabled the FAIL_ON_TRAILING_TOKENS option, to ensure the validation will fail if there is any text after a valid JSON besides whitespace.
Without this option, a JSON of the form {“email”:”example@com”}text will still appear as valid, even though it’s not.
4. Validation with Gson
Gson is another common library that allows us to validate raw JSON values using the same approach. It’s a complex tool that’s used for Java object mapping with different types of JSON handling.
4.1. Maven Dependency
Let’s add the gson Maven dependency:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>Copy
4.2. Non-Strict Validation
Gson provides JsonParser to read specified JSON into a tree of JsonElements. Consequently, it guarantees that we get JsonSyntaxException if there’s an error while reading.
Therefore, we can use the parse() method to compute String and handle Exception in case of a malformed JSON value:
public boolean isValid(String json) {
try {
JsonParser.parseString(json);
} catch (JsonSyntaxException e) {
return false;
}
return true;
}Copy
Let’s write some tests to check the main cases:
String json = "{\"email\": \"example@com\", \"name\": \"John\"}";
assertTrue(validator.isValid(json));
String json = "[{\"email\": \"example@com\", \"name\": \"John\"}]";
assertTrue(validator.isValid(json));Copy
The main difference of this approach is that the Gson default strategy considers separate string and numeric values to be valid as part of the JsonElement node. In other words, it considers a single string or number as valid as well.
For example, let’s see how it works with a single string:
String json = "Invalid_Json";
assertTrue(validator.isValid(json));Copy
However, if we want to consider such values as malformed, we need to enforce a strict type policy on our JsonParser.
4.3. Strict Validation
To implement a strict type policy, we create a TypeAdapter and define the JsonElement class as a required type match. As a result, JsonParser will throw a JsonSyntaxException if a type is not a JSON object or array.
We can call the fromJson() method to read raw JSON using a specific TypeAdapter:
final TypeAdapter<JsonElement> strictAdapter = new Gson().getAdapter(JsonElement.class);
public boolean isValid(String json) {
try {
strictAdapter.fromJson(json);
} catch (JsonSyntaxException | IOException e) {
return false;
}
return true;
}Copy
Finally, we can check whether a JSON is valid:
String json = "Invalid_Json";
assertFalse(validator.isValid(json));Copy
5. Conclusion
In this article, we’ve seen different ways to check whether a String is valid JSON.
Each approach has its advantages and limitations. While the JSON API can be used for simple object validation, the Gson can be more extensible for raw value validation as part of a JSON object. However, the Jackson is easier to use. Therefore, we should use the one that fits better.
Also, we should check if some library is already in use or applies for the rest of the goals as well.
As always, the source code for the examples is available over on GitHub.
Check Whether a String Is Valid JSON in Java | Baeldung