5

This is an example of the kind JSON I'm trying to consume using GSON:

{
    "person": {
        "name": "Philip"
        "father.name": "Yancy"
    }
}

I was wondering if it were possible to deserialize this JSON into the following structure:

public class Person
{
    private String name;
    private Father father; 
}

public class Father
{
    private String name;
}

So that:

p.name == "Philip"
p.father.name == "Yancy"

Currently I am using @SerializedName to obtain property names containing a period, e.g.:

public class Person
{
    private String name;

    @SerializedName("father.name")
    private String fathersName; 
}

However, that's not ideal.

From looking at the documentation it doesn't appear to be immediately possible but there may be something I have missed - I'm new to using GSON.

Unfortunately I cannot change the JSON I'm consuming and I'm reluctant to switch to another JSON parsing library.

Jonathan
  • 20,053
  • 6
  • 63
  • 70
  • I don't know GSON well enough, but perhaps it has it's own Parser interface you can implement which gives you access to json key/values with which you can choose to do whatever you like eg. create `Person` and `Father` objects. – Sotirios Delimanolis Apr 24 '13 at 14:30

2 Answers2

4

As far as I understand you can't do it in a direct way, because Gson will understand father.name as a single field.

You need to write your own Custom Deserializer. See Gson user's guide instructions here.

I've never tried it, but it doesn't seem to be too difficult. This post could be also helpful.

Taking a look at Gson's user guide and the code in that post, you'll need something like this:

private class PersonDeserializer implements JsonDeserializer<Person> {

  @Override
  public Person deserialize(JsonElement json, Type type,
        JsonDeserializationContext context) throws JsonParseException {

    JsonObject jobject = (JsonObject) json;

    Father father = new Father(jobject.get("father.name").getAsString());

    return new Person(jobject.get("name").getAsString(), father);
  }  
}

Assuming that you have suitable constructors...

And then:

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Person.class, new PersonDeserializer());
Gson gson = gsonBuilder.create();
Person person = gson.fromJson(jsonString, Person.class);

And Gson will call your deserializer in order to deserialize the JSON into a Person object.

Note: I didn't try this code, but it should be like this or something very similar.

Community
  • 1
  • 1
MikO
  • 18,243
  • 12
  • 77
  • 109
0

I couldn't do this with just Gson. I need a new library 'JsonPath'. I used Jackson's ObjectMapper to convert the object to string but you can easily use Gson for this.

public static String getProperty(Object obj, String prop) {
    try {
        return JsonPath.read(new ObjectMapper().writeValueAsString(obj), prop).toString();
    } catch (JsonProcessingException|PathNotFoundException ex) {
        return "";
    }
}

// 2 dependencies needed:
// https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
// https://mvnrepository.com/artifact/com.jayway.jsonpath/json-path



// usage:
String motherName = getProperty(new Person(), "family.mother.name");


// The Jackson can be easily replaced with Gson:
new Gson().toJson(obj)
JamesD
  • 591
  • 5
  • 10