繁体   English   中英

将对象列表转换为Json字符串时发生Stackoverflow错误

[英]Stackoverflow error occuring when converting Object list to Json string

我有一个Java RESTapi,我想将我的自定义Pet对象的列表转换为Json,并将其显示在端点中。

这是我到目前为止所拥有的:

@Path("/allPets")
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getPetsfromCollection() {
    List<Pet> petList = new ArrayList<>();
    petList.addAll(facade.returnAllPets());

    String json = gson.toJson(petList);

    //TODO return proper representation object
     return Response.ok().entity(json).build();
}

我正在使用Facade模式,我有一种方法可以将Java实体添加到列表中:

EntityManagerFactory emf = Persistence.createEntityManagerFactory("PetHospitaljpa");


public Collection<Pet> returnAllPets (){

    EntityManager  em = emf.createEntityManager();
    //vi laver en typed query for at specificere hvilken datatype, 
    // det er vi leder efter, i dette tilfælde er det en Pet
    TypedQuery<Pet> query = em.createNamedQuery("Pet.findAll", Pet.class);
    return query.getResultList();
}

我正在返回一个集合,以防我想稍后将ArrayList的数据结构更改为其他内容。

我尝试了几种解决方法,但我不断收到堆栈溢出错误。

Iøm意识到这个事实,我需要使用DTO,而且我已经制定了一个自定义方法来将实体更改为DTO:

public static DTOPet converttoDTO(Pet entity){

   DTOPet dto = new DTOPet();
   dto.setId(entity.getId());
   dto.setName(entity.getName());
   dto.setBirth(entity.getBirth());
   dto.setDeath(entity.getDeath());
   dto.setSpecies(entity.getSpecies());

   return dto;
}

我不确定这是不是很好的代码练习如果我还有别的东西可以改为将一组实体转换成DTO?

如指出。 出现问题是因为我有一个循环引用。

在我的Pet Entity类中:

@ManyToOne
private Owner ownerId;

在我的所有者实体类中:

@OneToMany(mappedBy = "ownerId")
private Collection<Pet> petCollection;

我的宠物类:

    /*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package Entities;

import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;

/**
 *
 * @author kristoffer
 */
@Entity
@Table(name = "pet")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Pet.findAll", query = "SELECT p FROM Pet p")
    , @NamedQuery(name = "Pet.findById", query = "SELECT p FROM Pet p WHERE p.id = :id")
    , @NamedQuery(name = "Pet.findByName", query = "SELECT p FROM Pet p WHERE p.name = :name")
    , @NamedQuery(name = "Pet.findByBirth", query = "SELECT p FROM Pet p WHERE p.birth = :birth")
    , @NamedQuery(name = "Pet.findBySpecies", query = "SELECT p FROM Pet p WHERE p.species = :species")
    , @NamedQuery(name = "Pet.findByDeath", query = "SELECT p FROM Pet p WHERE p.death = :death")})
public class Pet implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Integer id;
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 45)
    @Column(name = "name")
    private String name;
    @Basic(optional = false)
    @NotNull
    @Column(name = "birth")
    @Temporal(TemporalType.DATE)
    private Date birth;
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 45)
    @Column(name = "species")
    private String species;
    @Column(name = "death")
    @Temporal(TemporalType.DATE)
    private Date death;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "petId")
    private Collection<Event> eventCollection;
    @JoinColumn(name = "owner_id", referencedColumnName = "id")
    @ManyToOne
    private Owner ownerId;

    public Pet() {
    }

    public Pet(Integer id) {
        this.id = id;
    }

    public Pet(Integer id, String name, Date birth, String species) {
        this.id = id;
        this.name = name;
        this.birth = birth;
        this.species = species;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Date getBirth() {
        return birth;
    }

    public void setBirth(Date birth) {
        this.birth = birth;
    }

    public String getSpecies() {
        return species;
    }

    public void setSpecies(String species) {
        this.species = species;
    }

    public Date getDeath() {
        return death;
    }

    public void setDeath(Date death) {
        this.death = death;
    }

    @XmlTransient
    public Collection<Event> getEventCollection() {
        return eventCollection;
    }

    public void setEventCollection(Collection<Event> eventCollection) {
        this.eventCollection = eventCollection;
    }

    public Owner getOwnerId() {
        return ownerId;
    }

    public void setOwnerId(Owner ownerId) {
        this.ownerId = ownerId;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Pet)) {
            return false;
        }
        Pet other = (Pet) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "Pet{" + "id=" + id + ", name=" + name + ", birth=" + birth + ", species=" + species + ", death=" + death + ", eventCollection=" + eventCollection + ", ownerId=" + ownerId + '}';
    }   
}

编辑:我尝试创建一个方法,我将所有对象转换为DTO,但显示时字符串仍为空:

 @Path("/allPets")
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getPetsfromCollection() { 

    //med denne metode skal vi bruge et DTO(data transfer object til at formatere til Json)

    List<Pet> petList = new ArrayList<>();
    List<DTOPet> DTOPetList = new ArrayList<>();

    petList.addAll(facade.returnAllPets());
    for(Pet pet: petList){
        DTOPet dtopet = EntitytoDTO.converttoDTO(pet);
        DTOPetList.add(dtopet);
    }

    String json = gson2.toJson(DTOPetList);
     return Response.ok().entity(json).build();
}

当我使用调试器时,使用正确的参数成功创建新列表,但是就像[{},{},{},{}]一样创建了String JSON,即使我使用了GSON

如果没有看到“Pet”类的外观,就很难找出问题所在。 我怀疑你的Pet类中有另一个类的变量,它也有一个对pet类本身的引用(创建一个循环引用会导致序列化过程中的堆栈溢出)

您需要检测错误的位置。 我建议添加调试信息,比如

@Path("/allPets")
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getPetsfromCollection() {
    log.debug("getPetsfromCollection start");
    List<Pet> petList = new ArrayList<>(facade.returnAllPets());
    log.debug("petList" + petList.length());

    String json = gson.toJson(petList);
    log.debug("json " + json);

    //TODO return proper representation object
     return Response.ok().entity(json).build();
}


EntityManagerFactory emf = Persistence.createEntityManagerFactory("PetHospitaljpa");
public Collection<Pet> returnAllPets (){
    log.debug("returnAllPets start"); 
    EntityManager  em = emf.createEntityManager();
    log.debug("createNamedQuery start"); 
    TypedQuery<Pet> query = em.createNamedQuery("Pet.findAll", Pet.class);
    log.debug("single result" + query.getSingleResult() ); 

    TypedQuery<Pet> query = em.createNamedQuery("Pet.findAll", Pet.class);
    log.debug("list result" + query.getResultList()); 

    TypedQuery<Pet> query = em.createNamedQuery("Pet.findAll", Pet.class);
    return query.getResultList();
}

PS另外,请显示Pet类,可能是这个类的问题。

更新 :我建议也尝试临时删除:

@OneToMany(cascade = CascadeType.ALL, mappedBy = "petId")
private Collection<Event> eventCollection;

和/或

@JoinColumn(name = "owner_id", referencedColumnName = "id")
@ManyToOne
private Owner ownerId;

并检查你是否有这样的SO例外。 看起来像事件或所有者表太大或具有循环依赖性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM