Johnny Fee
Johnny Fee

Reputation: 131

Is there a solution about Gson "circular reference"?

I have found many articles about the circular reference with Gson, but I can't find an elegant solution.

As I know, some solutions is:

But as a general question, is there some common strategy to solve the problem?

Upvotes: 13

Views: 10116

Answers (4)

FabianoLothor
FabianoLothor

Reputation: 2985

Yes, you can use:

new ObjectMapper().writeValueAsString(yourObject);

You might need @JsonBackReference as well.

Upvotes: 0

Lei Z
Lei Z

Reputation: 203

I am looking into this issue as well. Gson does not provide a default solution so far. What you can do is:

Option 1: Create an exclusion strategy which implements ExclusionStrategy to exclude the class and/or field in the circular reference;

Option 2: Use annotations to mark the field to be transient to avoid serialization;

Option 3: Create your own type adapter

Upvotes: -2

Diego Victor de Jesus
Diego Victor de Jesus

Reputation: 3023

Since Gson doesn't properly handle circular references, and in some cases you may need to call the parent entity from its child, you can do this. Say we have:

@Entity
@Table(name = "servers_postgres")
public class PostgresServer implements Serializable {

    public PostgresServer() {
        this.tables = new ArrayList<>();
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id_server")
    private Integer serverId;

    @OneToMany(orphanRemoval = true, mappedBy = "server", fetch = FetchType.EAGER)
    @Cascade(org.hibernate.annotations.CascadeType.ALL)
    private List<PostgresTable> tables;

    @Column(length = 250)
    private String serverAddress;

    @Column(length = 250)
    private String name;
}

and

@Entity
@Table(name = "postgres_tables")
    public class PostgresTable implements Serializable {

        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "id_table")
        private Integer tableId;

        @Column(length = 250)
        private String name;

        @ManyToOne()
        @JoinColumn(name = "id_server", foreignKey = @ForeignKey(name = "fk_postgres_tables"))
        private PostgresServer server;
    }

In this case, you may need to get a PostgresServer reference from a PostgresTable entity. So, instead of excluding PostgresServer from serialization, you simply set its List of tables to null. For example:

//Assuming a List<PostgresTable>...
postgresTables.forEach(postgresTable -> postgresTable.getServer().setTables(null));

This is how i solve circular references with Gson. Hope that helps someone.

Upvotes: -1

StaxMan
StaxMan

Reputation: 116610

As far as I know there is no automated solution for circular references in Gson. The only JSON-producing library I know of that handles circular references automatically is XStream (with Jettison backend).

EDIT: Jackson also supports handling of circular references with @JsonIdentityInfo annotation; so while not automatic (you do need to mark references that need Object Id handling), it does allow solving most cases.

Upvotes: 4

Related Questions