gson.toJson()在Servlet中抛出StackOverflowError

i.f*_*yza 2 java json servlets java-ee angularjs

我有客户端对象列表

List<Client> clientsList=new ArrayList<Client>();
clientsList=clientDao.GetAllClients();
Run Code Online (Sandbox Code Playgroud)

实体客户端将其他列表作为属性:

@ManyToOne(optional=false)
private User createdBy;


@ManyToMany(mappedBy = "Clients")
private Set<ClientType> Types=new HashSet();


@ManyToOne(optional=false)
private LeadSource id_LeadSource;
@ManyToOne(optional=false)
private Agencie id_Agencie;

@OneToMany(cascade=CascadeType.ALL,mappedBy="Owner")
private Set<Propertie> properties=new HashSet();

@OneToMany(cascade=CascadeType.ALL,mappedBy="buyer")
private Set<Sale> sales=new HashSet();

@OneToMany(cascade=CascadeType.ALL,mappedBy = "client")
private Set<Rent> Rents=new HashSet();

@OneToMany(cascade=CascadeType.ALL,mappedBy = "clientDoc")
private Set<Document> Docuements=new HashSet();
Run Code Online (Sandbox Code Playgroud)

当我尝试将客户端列表转换为json格式时

out.write(new Gson().toJson(clientsList));
Run Code Online (Sandbox Code Playgroud)

我收到此错误:

java.lang.StackOverflowError
at com.google.gson.stream.JsonWriter.beforeName(JsonWriter.java:603)
at com.google.gson.stream.JsonWriter.writeDeferredName(JsonWriter.java:401)
at com.google.gson.stream.JsonWriter.value(JsonWriter.java:512)
at com.google.gson.internal.bind.TypeAdapters$8.write(TypeAdapters.java:270)
at com.google.gson.internal.bind.TypeAdapters$8.write(TypeAdapters.java:255)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:113)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:240)
Run Code Online (Sandbox Code Playgroud)

Nes*_*kil 12

那是因为您的实体具有双向连接.所以例如Client有一组Rents和每个租金都有参考Client.当您尝试序列化一个Client序列化的Rents,然后你必须每个序列ClientRent等等.这是导致这种情况的原因StackOverflowError.

要解决这个问题,你必须将一些属性标记为transient(或使用一些类似的anotation),例如使用transient Client.Rent然后任何编组lib都会忽略这个属性.

在GSON的情况下,你可以做其他方式标记你的领域被列入使用JSON要@Expose与创建GSON对象:

Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
Run Code Online (Sandbox Code Playgroud)

PS另外,我想提一下将JPA实体转换为json并将其发送到某个地方通常不是一个好主意.我建议创建一个DTO(数据传输对象)类,你只包括您所需要的信息和最理想的是采用唯一的简单的类型,如int,Date,String等等.如果您对此方法有疑问,可以谷歌搜索DTO,Data Transfer Object或点击以下链接:https://www.tutorialspoint.com/design_pattern/transfer_object_pattern.htm