java - 从 JPA 实体创建 Gson 对象抛出StackOverflowError 异常

标签 java json jpa jackson set

我有一个 JPA 实体“Users”,当我尝试通过 Gson 转换为 Json 时,出现 StackOverflowError 异常

@GetMapping("/users")
public ResponseEntity getUsers() {

  List<Users> users = userRepository.findAll();
  Gson gson = new GsonBuilder().setDateFormat("dd/MMM/yyyy HH:mm:ss").create();
  String json = gson.toJson(users);

....

}

用户实体是

@Table(uniqueConstraints={@UniqueConstraint(columnNames = {"Email"})})
@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString
@JsonNaming(PropertyNamingStrategy.UpperCamelCaseStrategy.class)
public class Users {

    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    private Long Id;

    @NotNull
    private String Name;

    @NotNull
    private String Email;

    @CreationTimestamp
    @Temporal(value=TemporalType.TIMESTAMP)
    private Date DateCreated;

    @Transient
    private String Password;

    @ToString.Exclude
    @JsonIgnore
    @OneToOne(mappedBy = "user", fetch = FetchType.LAZY)
    private SecUser secuser;

    @PrePersist
    protected void onCreate() {
        DateCreated = new Date();
    }

    @JsonIgnore
    @OneToMany(mappedBy = "user", fetch = FetchType.EAGER)
    private final Set<Activity> activity = new HashSet<>();

}

我得到了异常(exception)...

java.lang.StackOverflowError: null
    at java.base/sun.util.locale.provider.LocaleProviderAdapter.getAdapter(LocaleProviderAdapter.java:239) ~[na:na] java.base/java.text.DateFormatSymbols.getProviderInstance(DateFormatSymbols.java:368) ~[na:na]
    at java.base/java.text.DateFormatSymbols.getInstance(DateFormatSymbols.java:346) ~[na:na]
    at java.base/java.util.Calendar.getDisplayName(Calendar.java:2142) ~[na:na]
    at java.base/java.text.SimpleDateFormat.subFormat(SimpleDateFormat.java:1156) ~[na:na]
    at java.base/java.text.SimpleDateFormat.format(SimpleDateFormat.java:997) ~[na:na]
    at java.base/java.text.SimpleDateFormat.format(SimpleDateFormat.java:967) ~[na:na]
    at java.base/java.text.DateFormat.format(DateFormat.java:374) ~[na:na]
    at com.google.gson.internal.bind.DateTypeAdapter.write(DateTypeAdapter.java:96) ~[gson-2.8.5.jar:na]
    at com.google.gson.internal.bind.DateTypeAdapter.write(DateTypeAdapter.java:46) ~[gson-2.8.5.jar:na]
    at com.google.gson.internal.bind.TypeAdapters$26$1.write(TypeAdapters.java:587) ~[gson-2.8.5.jar:na]
    at com.google.gson.internal.bind.TypeAdapters$26$1.write(TypeAdapters.java:580) ~[gson-2.8.5.jar:na]
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69) ~[gson-2.8.5.jar:na]
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:127) ~[gson-2.8.5.jar:na]
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:245) ~[gson-2.8.5.jar:na]
    at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:1018) ~[gson-2.8.5.jar:na]

我已经使用非实体对象成功地实现了此策略。我怎样才能让它发挥作用?

最佳答案

问题在于序列化双向一对一和一对多关系。 (我猜它是双向的,因为它们是mappedBy =“user”)。

这是因为@JsonIgnore是来自jackson的注释,而不是来自gson的注释。要从 gson 中的序列化中排除字段,您必须采取其他方式 - 使用 @Expose 注释每个其他字段,以便未注释的字段(在您的情况下 - secuser code> 和 activity)不会被序列化。

其他解决方案是使所有不可序列化字段transient,但由于它是一个@Entity,因此这无法完成任务。如果首先映射到 DTO,它就会起作用。尽管有很多附加注释,第一个解决方案似乎更简单。

有关 gson 中排除的更多信息,您可以找到 here .

最后一个可能的解决方案 - 使用 jackson 而不是 gson。

关于java - 从 JPA 实体创建 Gson 对象抛出StackOverflowError 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57667637/

相关文章:

java - 测试抽象类抛出 InstantiationException

ruby-on-rails - 如何在 JSON API 的 RSpec 测试中传递身份验证 token ?

jpa - JPQL 不断抛出 The expression is not a valid conditional expression

java - 正则表达式检查 Android 中的多个条件

java - ReSTLet:在 HTTP 请求中发送 xml

Python 解析带有空格分隔子字段的 JSON 值

c++ - 将字符串转换为 const *json 后,在传递 json 对象时,显示失败 : (IsObject()), 如何解决?

maven - Webapp 找不到持久性单元。范围内没有名为 'X' 的持久性单元可用

java - 为什么 Consul 尝试连接到我的数据库?

java - android 背景颜色 xml 标签在 android studio 中不起作用