Converting JSON message to Groovy Bean

The power of the Java/Groovy type system, reflection API, and other goodies may be very handy if you need to make more type-safe code.

JSON by definition is not doing any type checking, but it is possible to map the JSON data to the Java/Groovy objects to present data inside your application and get access to type information. And that's what we will demonstrate in this recipe.

Getting ready

First of all let's define a Groovy Bean (POGO) class, which holds data representing some vehicle information:

package org.groovy.cookbook

import groovy.transform.ToString

@ToString
class Vehicle {

  static enum FuelType { DIESEL, PETROL, GAS, ELECTRIC }
  static enum TransmissionType { MANUAL, AUTOMATIC }

  @ToString
  static class Transmission {
    long gears
    TransmissionType type
  }

  String brand
  String model
  FuelType fuel
  Long releaseYear
  Transmission transmission

}

As you can notice it's nothing, but a set of fields of simple types, enumerations, and a nested class, which again consists of simple type fields. In order for that class to be available for the conversion script, let's place it into a vehicle.groovy file and compile it with the groovyc command:

groovyc vehicle.groovy

The JSON document to which we want to map the class is the one defined in the recipe, Validating JSON messages. Create a vehicle.json file in the same directory as the vehicle.groovy.

To simplify the mapping, we used the same property names in both, JSON message and the Vehicle class.

How to do it...

Create a new Groovy script, convert.groovy, making sure that it's located in the same folder as the JSON file.

  1. Add the following code to the script:
    import groovy.json.JsonSlurper
    import org.groovy.cookbook.Vehicle
    
    def reader = new FileReader('vehicle.json')
    def jsonVehicle = new JsonSlurper().parse(reader)
    
    def vehicle = new Vehicle (
      brand: jsonVehicle.brand,
      model: jsonVehicle.model,
      transmission: new Vehicle.Transmission(
        gears: jsonVehicle.transmission.gears,
        type: jsonVehicle.transmission.type),
      releaseYear: jsonVehicle.releaseYear,
      fuel: jsonVehicle.fuel)
    
    println vehicle
  2. Run the script in a usual way:
    groovy convert.groovy
    
  3. The println command outputs:
    org.groovy.cookbook.Vehicle(Mazda, 5, PETROL, 2007,
       org.groovy.cookbook.Vehicle$Transmission(5, MANUAL))
    

How it works...

Groovy performs some of the data type mapping automatically for us; making the conversion code simpler. For example, jsonVehicle.fuel is actually a String, but it is transformed to FuelType enumeration automatically since the values are matching. Also, jsonVehicle.transmission.gears is a String in our original JSON message (because it is included in the double quotes), but it is still safely converted to a long field in the Transmission object.

Thanks to the @ToString annotation, the Vehicle class shows all its internal data upon printing by the last line of the script.

There's more...

Writing the conversion code for every possible type you may need, is time consuming. Fortunately, existing third-party libraries come to the rescue. In the following sections, we will show how Groovy Bean conversion can be achieved with the JSON-lib, Jackson and GSON libraries. Please note that for the next examples to work the Vehicle class is imported, therefore, it must be extracted to a Vehicle.groovy class and added to the classpath when running the code.

  • JSON-lib can be used in the following way:
    @Grapes([
      @Grab(group='net.sf.json-lib',
        module='json-lib',
        version='2.3',
        classifier='jdk15'),
      @Grab('xom:xom:1.2.5')
    ])
    import net.sf.json.JSONObject
    import org.groovy.cookbook.Vehicle
    
    def file = new File('vehicle.json')
    def jsonObject = JSONObject.fromObject(file.text)
    
    println JSONObject.toBean(jsonObject, Vehicle)
  • Jackson can be used in the following way:
    @Grab('com.fasterxml.jackson.core:jackson-databind:2.1.0')
    import com.fasterxml.jackson.databind.ObjectMapper
    import org.groovy.cookbook.Vehicle
    
    def mapper = new ObjectMapper()
    def file = new File('vehicle.json')
    
    println mapper.readValue(file, Vehicle)
  • GSON can be used in the following way:
    @Grab('com.google.code.gson:gson:2.2.2')
    import com.google.gson.Gson
    
    import org.groovy.cookbook.Vehicle
    
    def gson = new Gson()
    def reader = new FileReader('vehicle.json')
    
    println gson.fromJson(reader, Vehicle)

All of those frameworks produce similar results, and they can be further tweaked for more complex data conversion requirements.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.123.155