Deserialize JSON data in Java

In my previous post, I introduced a way to generate Java classes out of actual JSON data. This time, I will talk about how you can actually call Jenkins REST API and deserialize the data to usable objects.

Jenkins can give you the list of slave nodes in JSON format with the URL like the following.

http://your-jenkins-server/computer/api/json

When you hit the URL with your browser, it gives you the JSON data like the following.

{
  "_class" : "hudson.model.ComputerSet",
  "busyExecutors" : 0,
  "computer" : [
    {
      "_class" : "hudson.model.Hudson$MasterComputer",
      "actions" : [
        
      ],
      "assignedLabels" : [
        {
          "name" : "master"
        }
      ],
      "description" : "the master Jenkins node",
      "displayName" : "master",
      "executors" : [
        {
          
        }
      ],
      "icon" : "computer.png",
      "iconClassName" : "icon-computer",
      "idle" : true,
      "jnlpAgent" : false,
      "launchSupported" : true,
      "loadStatistics" : {
        "_class" : "hudson.model.Label$1"
      },
      "manualLaunchAllowed" : true,
      "monitorData" : {
        "hudson.node_monitors.SwapSpaceMonitor" : {
          "_class" : "hudson.node_monitors.SwapSpaceMonitor$MemoryUsage2",
          "availablePhysicalMemory" : 270237696,
          "availableSwapSpace" : 4160737280,
          "totalPhysicalMemory" : 3954294784,
          "totalSwapSpace" : 4160745472
        },
        "hudson.node_monitors.TemporarySpaceMonitor" : {
          "_class" : "hudson.node_monitors.DiskSpaceMonitorDescriptor$DiskSpace",
          "timestamp" : 1548569608435,
          "path" : "/tmp",
          "size" : 38455533568
        },
        "hudson.node_monitors.DiskSpaceMonitor" : {
          "_class" : "hudson.node_monitors.DiskSpaceMonitorDescriptor$DiskSpace",
          "timestamp" : 1548569607737,
          "path" : "/var/jenkins_home",
          "size" : 20490350592
        },
        "hudson.node_monitors.ArchitectureMonitor" : "Linux (amd64)",
        "hudson.node_monitors.ResponseTimeMonitor" : {
          "_class" : "hudson.node_monitors.ResponseTimeMonitor$Data",
          "timestamp" : 1548569607764,
          "average" : 0
        },
        "hudson.node_monitors.ClockMonitor" : {
          "_class" : "hudson.util.ClockDifference",
          "diff" : 0
        }
      },
      "numExecutors" : 1,
      "offline" : false,
      "offlineCause" : null,
      "offlineCauseReason" : "",
      "oneOffExecutors" : [
        
      ],
      "temporarilyOffline" : false
    },
    {
      "_class" : "hudson.slaves.SlaveComputer",
      "actions" : [
        
      ],
      "assignedLabels" : [
        {
          "name" : "Linux"
        },
        {
          "name" : "build-lnx-01"
        }
      ],
      "description" : "",
      "displayName" : "build-lnx-01",
      "executors" : [
        {
          
        }
      ],
      "icon" : "computer.png",
      "iconClassName" : "icon-computer",
      "idle" : true,
      "jnlpAgent" : true,
      "launchSupported" : false,
      "loadStatistics" : {
        "_class" : "hudson.model.Label$1"
      },
      "manualLaunchAllowed" : true,
      "monitorData" : {
        "hudson.node_monitors.SwapSpaceMonitor" : {
          "_class" : "hudson.node_monitors.SwapSpaceMonitor$MemoryUsage2",
          "availablePhysicalMemory" : 270155776,
          "availableSwapSpace" : 4160737280,
          "totalPhysicalMemory" : 3954294784,
          "totalSwapSpace" : 4160745472
        },
        "hudson.node_monitors.TemporarySpaceMonitor" : {
          "_class" : "hudson.node_monitors.DiskSpaceMonitorDescriptor$DiskSpace",
          "timestamp" : 1548569608449,
          "path" : "/tmp",
          "size" : 38455533568
        },
        "hudson.node_monitors.DiskSpaceMonitor" : {
          "_class" : "hudson.node_monitors.DiskSpaceMonitorDescriptor$DiskSpace",
          "timestamp" : 1548569607743,
          "path" : "/home/jenkins",
          "size" : 20490350592
        },
        "hudson.node_monitors.ArchitectureMonitor" : "Linux (amd64)",
        "hudson.node_monitors.ResponseTimeMonitor" : {
          "_class" : "hudson.node_monitors.ResponseTimeMonitor$Data",
          "timestamp" : 1548569607767,
          "average" : 10
        },
        "hudson.node_monitors.ClockMonitor" : {
          "_class" : "hudson.util.ClockDifference",
          "diff" : -2
        }
      },
      "numExecutors" : 1,
      "offline" : false,
      "offlineCause" : null,
      "offlineCauseReason" : "",
      "oneOffExecutors" : [
        
      ],
      "temporarilyOffline" : false,
      "absoluteRemotePath" : "/home/jenkins"
    },
    {
      "_class" : "hudson.slaves.SlaveComputer",
      "actions" : [
        
      ],
      "assignedLabels" : [
        {
          "name" : "Windows"
        },
        {
          "name" : "build-win-01"
        }
      ],
      "description" : "",
      "displayName" : "build-win-01",
      "executors" : [
        {
          
        }
      ],
      "icon" : "computer-x.png",
      "iconClassName" : "icon-computer-x",
      "idle" : true,
      "jnlpAgent" : true,
      "launchSupported" : false,
      "loadStatistics" : {
        "_class" : "hudson.model.Label$1"
      },
      "manualLaunchAllowed" : true,
      "monitorData" : {
        "hudson.node_monitors.SwapSpaceMonitor" : null,
        "hudson.node_monitors.TemporarySpaceMonitor" : null,
        "hudson.node_monitors.DiskSpaceMonitor" : null,
        "hudson.node_monitors.ArchitectureMonitor" : null,
        "hudson.node_monitors.ResponseTimeMonitor" : null,
        "hudson.node_monitors.ClockMonitor" : null
      },
      "numExecutors" : 1,
      "offline" : true,
      "offlineCause" : null,
      "offlineCauseReason" : "",
      "oneOffExecutors" : [
        
      ],
      "temporarilyOffline" : false,
      "absoluteRemotePath" : null
    }
  ],
  "displayName" : "Nodes",
  "totalExecutors" : 2
}

Let’s deserialize the data!

package com.hoge.jenkins.lib;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class JenkinsServer extends Base implements IJenkinsServer
{
    public JenkinsServer()
    {

    }

    public ComputerCollection getComputers(String Url) throws IOException
    {
        var client = new OkHttpClient();
        var request = new Request.Builder()
                .url(Url)
                .get()
                .build();

        var call = client.newCall(request);
        var response = call.execute();

        var mapper = new ObjectMapper();
        return mapper.readValue(response.body().string(), ComputerCollection.class);
    }
}

The function getComputers uses OkHttp. I looked around for HTTP client component and I think OkHttp feels more modern than other components. It basically gets the JSON data via HTTP GET call and the last line of the function deserializes the data. Imagine having to parse the JSON data and write the code to convert the data to Java objects… This is a very clean way of consuming REST API data.

If you take a look at the deserialized objects in IntelliJ, it looks like the following image. The data is cleanly mapped to the usable objects in memory.

Evaluating the returned object

If you just try this yourself, you might get authentication error. I haven’t gone through how to include authentication header in the code. I will post another article how to add authentication code. I will be basically modifying the getComputers function in this post.

Author: admin

A software engineer in greater Seattle area

Leave a Reply

Your email address will not be published. Required fields are marked *