1. Overview

JSON is a widely employed structured data format typically used in most modern APIs and data services. It’s particularly popular in web applications due to its lightweight nature and compatibility with JavaScript.

Sometimes, it may be useful to sort the data before we display it in applications that fetch JSON.

In this quick tutorial, we’ll see a couple of approaches for sorting JSON objects in Java.

2. Getting Started

Let’s get started by defining a relatively simple JSON structure which models some imaginary Solar Events:

{
    "solar_events": [
        {
            "event_name": "Solar Eclipse",
            "date": "2024-04-08",
            "coordinates": {
                "latitude": 37.7749,
                "longitude": -122.4194
            },
            "size": "Large",
            "speed_km_per_s": 1000
        },
        {
            "event_name": "Solar Flare",
            "date": "2023-10-28",
            "coordinates": {
                "latitude": 0,
                "longitude": 0
            },
            "size": "Small",
            "speed_km_per_s": 100
        },
        {
            "event_name": "Sunspot",
            "date": "2023-11-15",
            "coordinates": {
                "latitude": 15,
                "longitude": -75
            },
            "size": "Large",
            "speed_km_per_s": 1500
        },
        {
            "event_name": "Coronal Mass Ejection",
            "date": "2024-01-10",
            "coordinates": {
                "latitude": -5,
                "longitude": 80
            },
            "size": "Medium",
            "speed_km_per_s": 500
        }
    ]
}

Throughout this tutorial, this JSON document will be the focus of our examples.

3. Using Jackson

In this first example, we’ll take a look at Jackson a multi-purpose Java library for processing JSON data.

First, we’ll need to add the jackson-databind dependency to our pom.xml:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.17.2</version>
</dependency>

We’ll also need to define a few simple POJO objects that we can use to deserialize our JSON string into a Java object:

class SolarEvent {
    @JsonProperty("event_name")
    private String eventName;
    @JsonProperty("date")
    private String date;
    @JsonProperty("coordinates")
    private Coordinates coordinates;
    @JsonProperty("type")
    private String type;
    @JsonProperty("class")
    private String eventClass;
    @JsonProperty("size")
    private String size;
    @JsonProperty("speed_km_per_s")
    private int speedKmPerS;

    // Getters and Setters
}

class Coordinates {
    @JsonProperty("latitude")
    private double latitude;

    @JsonProperty("longitude")
    private double longitude;

    // Getters and setters
}

We’ll also define a container object to hold our list of events:

class SolarEventContainer {
    @JsonProperty("solar_events")
    private List<SolarEvent> solarEvents;

    //Getters and setters
}

Now, we can go ahead and write a simple unit test to verify we can sort a list of solar events using a given attribute:

@Test
void givenJsonObjects_whenUsingJackson_thenSortedBySpeedCorrectly() throws IOException {
    ObjectMapper objectMapper = new ObjectMapper();
    SolarEventContainer container =
      objectMapper.readValue(new File("src/test/resources/solar_events.json"),
      SolarEventContainer.class);

    List<SolarEvent> events = container.getSolarEvents();
    Collections.sort(events, Comparator.comparingInt(event -> event.getSpeedKmPerS()));

    assertEquals(100, events.get(0).getSpeedKmPerS());
    assertEquals(500, events.get(1).getSpeedKmPerS());
    assertEquals(1000, events.get(2).getSpeedKmPerS());
    assertEquals(1500, events.get(3).getSpeedKmPerS());
}

Our first goal is to parse the JSON and deserialize it into our object model. For this, we’ve used Jackson’s standard ObjectMapper. We used the readValue() method to read the JSON from a file and convert our JSON into a SolarEventContainer object.

Now that we have a Java object model, we can go ahead and sort the objects based on any of the attributes in our class. For the sorting, we define a Comparator by using a lambda expression, and the comparingInt() static factory to sort our events using the getSpeedKmPerS() method.

Finally, our test confirmed that the speed attribute correctly ordered the events.

4. Using Gson

Now, let’s take a look at a similar approach using another popular JSON processing library Gson. As before, we’ll start by adding this dependency to our pom.xml:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.11.0</version>
</dependency>

As always, the latest version is available from the Maven Repository.

Sometimes, it might not always be possible to have our own internal Java object model to work with, so in this example, we’ll see how we can work with the JSON Java objects that are available directly from this library:

@Test
public void givenJsonObject_whenUsingGson_thenSortedBySizeCorrectly() throws FileNotFoundException {
    JsonReader reader = new JsonReader(new FileReader("src/test/resources/solar_events.json"));
    JsonElement element = JsonParser.parseReader(reader);
    JsonArray events = element.getAsJsonObject().getAsJsonArray("solar_events");
    List<JsonElement> list = events.asList();

    Collections.sort(list, (a, b) -> {
        double latA = a.getAsJsonObject()
          .getAsJsonObject("coordinates")
          .get("latitude")
          .getAsDouble();
        double latB = b.getAsJsonObject()
          .getAsJsonObject("coordinates")
          .get("latitude")
          .getAsDouble();
        return Double.compare(latA, latB);
    });

    assertEquals(-5, getJsonAttributeAsInt(list.get(0)));
    assertEquals(0, getJsonAttributeAsInt(list.get(1)));
    assertEquals(15, getJsonAttributeAsInt(list.get(2)));
    assertEquals(37, getJsonAttributeAsInt(list.get(3)));
}

private int getJsonAttributeAsInt(JsonElement element) {
    return element.getAsJsonObject()
      .getAsJsonObject("coordinates")
      .get("latitude")
      .getAsInt();
}

As we can see, we use a similar approach to read in our sample JSON file, but this time, we retrieve a list of JsonElement objects, which represents each entry in our solar_events.json file.

Likewise, we can now sort the elements in the list using the Collections.sort method by supplying a custom comparator to parse and select the required values from the JSON objects. This is certainly a bit more verbose than the previous example and vulnerable to errors if our JSON structure changes or we mistype a JSON object or attribute name.

Finally, this time around, we check the elements have been sorted correctly using the latitude value. We also provide a small utility method to help us extract the values from the JSON elements.

5. Conclusion

In this short article, we learned how to sort JSON objects using two popular JSON processing Java libraries.

In the first example, we saw how to use our own Java object model with the popular Jackson library. Latterly, we learned how to work directly with the object model supplied by the Gson library.

As always, the full source code of the article is available over on GitHub.