Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE

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>

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;
}

Let’s try it with a simple example:

String json = "{\"email\": \"example@com\", \"name\": \"John\"}";
assertTrue(validator.isValid(json));
String json = "Invalid_Json"; 
assertFalse(validator.isValid(json));

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));

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;
}

As a result, we can validate any value:

String json = "[{\"email\": \"example@com\", \"name\": \"John\"}]";
assertTrue(validator.isValid(json));

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>

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;
}

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));

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>

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;
}

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));

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));

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;
}

Finally, we can check whether a JSON is valid:

String json = "Invalid_Json";
assertFalse(validator.isValid(json));

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.

Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE
res – REST with Spring (eBook) (everywhere)
Comments are closed on this article!