Gson Advanced — Mapping of Circular References

In this blog post we'll deal with one particularly nasty topic: circular references. You might have heard about circular references in your computer science or math class on graphs. In a more practical explanation: it deals with the case when objects have a nested property to a different object, which then references back to the original one. This scenario will cause Gson to crash your app. If you want to know how you can deal with this, keep reading!

Of course, this is not the only post in our Gson series. If you're interested in the other topics, check out our series outline:

Gson Series Overview

Gson and the StackOverflowError

The alternative title of this blog post could have been: Why does Gson cause a java.lang.StackOverflowError?

Just think of it from a serialization perspective: as you've read in the nested objects blog post, Gson needs to create a new JSON subelement for every referenced object. If object A references to object B, Gson will need to create a subelement in A for B. If B references back to A, we're stuck in an infinite loop and will keep creating new subelements, which create new subelements, and so on. Eventually, this will trigger the StackOverflowError.

Let's visualize this scenario with some actual code:

public class UserCircular {  
    String name;
    String email;
    int age;
    boolean isDeveloper;

    // references to child & parent node
    UserCircular child;
    UserCircular parent;
}

Imagine your app builds a family tree. Then every family member might be wrapped in the UserCircular class you can see above. Alright, the child and parent property should probably be a list, but that doesn't change anything.

From a programming perspective, this is a total valid implementation. Unfortunately, you won't be able to serialize it. There's no JSON equivalent which holds the same data format, since we'll be stuck in that infinite loop.

The solution is simple: you'll have to exclude one graph reference from the serialization. You can read here more about various options to achieve this. A simple way would be to add transient to the parent property:

public class UserCircular {  
    String name;
    String email;
    int age;
    boolean isDeveloper;

    // references to child & parent node
    UserCircular child;
    transient UserCircular parent;
}

Internally nothing changes for your app. Nevertheless, parent would not be serialized anymore and you're out of that infinite loop:

{
  "age": 26,
  "childUser": {
    "age": 26,
    "email": "norman@futurestud.io",
    "isDeveloper": true,
    "name": "Norman"
  },
  "email": "norman@futurestud.io",
  "isDeveloper": true,
  "name": "Norman"
}

All the necessary data would still be serialized. The server would need to create the back-reference again, if that's required.

Outlook

In this blog post you've learned when Gson can run into an infinite loop and throws a StackOverflowError at you. You can solve this problem by excluding one graph pointer from the serialization.

If you've feedback or a question, let us know in the comments or on twitter @futurestud_io.

Make it rock & enjoy coding!

Explore the Library

Find interesting tutorials and solutions for your problems.