jsongoogle-cloud-platformgsongoogle-http-client

How do I deserialize a json String to Java Object in App Engine


I have a UI which sends this object - com.google.api.services.compute.model.Network in JSON format as part of a HTTP request. I need to deserialize this object to the Java object. How do I do that? I wrote a simple POJO like below to mimic the behaviour.

package com.techm.studio.client;

import java.io.IOException;

import com.google.api.services.compute.model.Network;
import com.google.api.services.compute.model.NetworkRoutingConfig;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class JSONTest {

    public static void main(String[] args) throws IOException {

        Network network = new Network();

        network.setName("k-network");
        network.setAutoCreateSubnetworks(false);
        network.setDescription("My test network on Google Cloud");
        network.setIPv4Range("10.0.0.0/16");
        network.setRoutingConfig(new NetworkRoutingConfig().setRoutingMode("REGIONAL"));

        String nwkJsonString = new GsonBuilder().setPrettyPrinting().create().toJson(network);
        System.out.println("JSON String from POJO ==>\n" + nwkJsonString);

        Network netwrkOut = new Gson().fromJson(nwkJsonString, Network.class);
        System.out.println(netwrkOut.toPrettyString()); 
    }

}

And this is the output I get.

JSON String from POJO ==>
{
  "IPv4Range": "10.0.0.0/16",
  "autoCreateSubnetworks": false,
  "description": "My test network on Google Cloud",
  "name": "k-network",
  "routingConfig": {
    "routingMode": "REGIONAL"
  }
}
Exception in thread "main" java.lang.IllegalArgumentException: Can not set com.google.api.services.compute.model.NetworkRoutingConfig field com.google.api.services.compute.model.Network.routingConfig to com.google.gson.internal.LinkedTreeMap
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
    at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)
    at java.lang.reflect.Field.set(Field.java:764)
    at com.google.api.client.util.FieldInfo.setFieldValue(FieldInfo.java:280)
    at com.google.api.client.util.FieldInfo.setValue(FieldInfo.java:241)
    at com.google.api.client.util.GenericData.put(GenericData.java:104)
    at com.google.api.client.util.GenericData.put(GenericData.java:48)
    at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:188)
    at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:145)
    at com.google.gson.Gson.fromJson(Gson.java:887)
    at com.google.gson.Gson.fromJson(Gson.java:852)
    at com.google.gson.Gson.fromJson(Gson.java:801)
    at com.google.gson.Gson.fromJson(Gson.java:773)
    at com.techm.studio.client.JSONTest.main(JSONTest.java:25)

I don't know if I have to register all the nested types upfront and how to do it.


Solution

  • It looks like com.google.api.services.* has it's own com.google.api.client.json.* package which should be used in this case to serialise model to JSON and deserialise JSON to model. See below example:

    import com.google.api.client.json.JsonGenerator;
    import com.google.api.client.json.JsonParser;
    import com.google.api.client.json.jackson2.JacksonFactory;
    import com.google.api.services.compute.model.Network;
    import com.google.api.services.compute.model.NetworkRoutingConfig;
    
    import java.io.StringWriter;
    
    public class GsonApp {
    
        public static void main(String[] args) throws Exception {
            Network network = new Network();
    
            network.setName("k-network");
            network.setAutoCreateSubnetworks(false);
            network.setDescription("My test network on Google Cloud");
            network.setIPv4Range("10.0.0.0/16");
            network.setRoutingConfig(new NetworkRoutingConfig().setRoutingMode("REGIONAL"));
    
            JacksonFactory jacksonFactory = new JacksonFactory();
            StringWriter writer = new StringWriter();
            try (JsonGenerator jsonGenerator = jacksonFactory.createJsonGenerator(writer)) {
                jsonGenerator.enablePrettyPrint();
                jsonGenerator.serialize(network);
            }
    
            String nwkJsonString = writer.toString();
            System.out.println("JSON String from POJO ==>\n" + nwkJsonString);
    
            JsonParser jsonParser = jacksonFactory.createJsonParser(nwkJsonString);
            Network netwrkOut = jsonParser.parse(Network.class);
            System.out.println(netwrkOut.toPrettyString());
        }
    }
    

    Above code prints:

    JSON String from POJO ==>
    {
      "IPv4Range" : "10.0.0.0/16",
      "autoCreateSubnetworks" : false,
      "description" : "My test network on Google Cloud",
      "name" : "k-network",
      "routingConfig" : {
        "routingMode" : "REGIONAL"
      }
    }
    {
      "IPv4Range" : "10.0.0.0/16",
      "autoCreateSubnetworks" : false,
      "description" : "My test network on Google Cloud",
      "name" : "k-network",
      "routingConfig" : {
        "routingMode" : "REGIONAL"
      }
    }
    

    And you do not need to use Gson.