Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reference parent object while deserializing a JSON using Gson

Given the following JSON:

{
    "authors": [{
        "name": "Stephen King",
        "books": [{
            "title": "Carrie"
        }, {
            "title": "The Shining"
        }, {
            "title": "Christine"
        }, {
            "title": "Pet Sematary"
        }]
    }]
}

And this object structure:

public class Author {
    private List<Book> books;
    private String name;
}

public class Book {
    private transient Author author;
    private String title;
}

Is there a way, using the Google Java library Gson, to deserialize the JSON and that the books objects has a reference to the "parent" author object?

Is it possible without using a custom deserializer?

  • If yes: How?
  • If no: Is is still possible to do it with a custom deserializer?
like image 741
Thermech Avatar asked Jan 07 '23 19:01

Thermech


1 Answers

In this case, I would implement a custom JsonDeserializer for the parent object, and propagate the Author info, like so:

public class AuthorDeserializer implements JsonDeserializer<Author> {
    @Override
    public Author deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        final JsonObject authorObject = json.getAsJsonObject();

        Author author = new Author();
        author.name = authorObject.get("name").getAsString();

        Type booksListType = new TypeToken<List<Book>>(){}.getType();
        author.books = context.deserialize(authorObject.get("books"), booksListType);

        for(Book book : author.books) {
            book.author = author;
        }

        return author;
    }   
}

Note that my example omits error checking. You would use it like so:

Gson gson = new GsonBuilder()
    .registerTypeAdapter(Author.class, new AuthorDeserializer())
    .create();

To show it working, I pulled off just the "authors" key from your example JSON, allowing me to do this:

JsonElement authorsJson  = new JsonParser().parse(json).getAsJsonObject().get("authors");

Type authorList = new TypeToken<List<Author>>(){}.getType();
List<Author> authors = gson.fromJson(authorsJson, authorList);
for(Author a : authors) {
    System.out.println(a.name);
    for(Book b : a.books) {
        System.out.println("\t " + b.title + " by " + b.author.name);
    }
}

Which printed:

Stephen King
     Carrie by Stephen King
     The Shining by Stephen King
     Christine by Stephen King
     Pet Sematary by Stephen King
like image 124
nickb Avatar answered Jan 15 '23 06:01

nickb