tig*_*k89 7 java json hibernate jackson gson
这些天我正在努力处理 Hibernate 实体和 JSON,尽管存在很多关于该对象的问题,但我还无法在存在循环依赖项的情况下进行序列化。我尝试了 Gson 和 Jackson,但没有取得太大进展。这是我的对象的摘录。这是“父”类。
@Entity
public class User extends RecognizedServerEntities implements java.io.Serializable
{
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
private Integer id;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "user", orphanRemoval = false)
@Cascade({CascadeType.SAVE_UPDATE})
private Set<Thread> threads = new HashSet<Thread>(0);
//...other attributes, getters and setters
}
Run Code Online (Sandbox Code Playgroud)
这是“儿童”班
@Entity
@Table(name = "thread")
public class Thread extends RecognizedServerEntities implements java.io.Serializable
{
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
private Integer id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "author", nullable = true)
private User user;
//...other attributes, getters and setters
}
Run Code Online (Sandbox Code Playgroud)
我编写了一个简单的类来测试 gson 和 jackson 功能;如前所述,他们都提出了例外。
public class MyJsonsTest
{
private static User u;
public static void main(String[] args)
{
u = new User("mail", "password", "nickname", new Date());
u.setId(1); // Added with EDIT 1
// testGson();
testJackson();
}
private static void testJackson()
{
Thread t = new Thread("Test", u, new Date(), new Date());
t.setId(1); // Added with EDIT 1
u.getThreads().add(t);
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
try
{
mapper.writeValue(new File("result.json"), u);
}
catch {/[various exceptions catched, but a JsonMappingException was thrown]}
}
private static void testGson()
{
Gson gson = new Gson();
System.out.println(u.toString());
System.out.println(gson.toJson(u, User.class));
Thread t = new Thread("Test", u, new Date(), new Date());
u.getThreads().add(t);
//This raise an exception overflow
System.out.println(gson.toJson(u, User.class));
}
}
Run Code Online (Sandbox Code Playgroud)
为了解决这个问题,在jackson这边,我尝试使用这个注释
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
Run Code Online (Sandbox Code Playgroud)
在 User 和 Thread 类上。然而,它并不能解决问题。在 gson 方面,我阅读了有关 GraphAdapterBuilder 类的信息,但我无法正确使用它。我没有找到任何 jar,所以我从这里复制/粘贴了源代码。然而,这一行有一个编译时错误
private final ConstructorConstructor constructorConstructor = new ConstructorConstructor();
Run Code Online (Sandbox Code Playgroud)
因为 ConstructorConstructor() 未定义;正确的语法应该是
ConstructorConstructor(Map<Type>, InstanceCreator<?> instanceCreators)
Run Code Online (Sandbox Code Playgroud)
那么,这个问题有没有一个明确的解决方案呢?显然,我不能使用transient变量。
我终于找到了杰克逊的问题。在测试类中,我忘记初始化id字段(在实际场景中它是由数据库初始化的),这就是异常的原因。当我最终设置 id 时,一切正常。这是输出
{
"id" : 1,
"email" : "mail",
"password" : "password",
"nick" : "nickname",
"registeredDate" : 1414703168409,
"threads" : [ {
"id" : 1,
"thread" : null,
"user" : 1,
"title" : "Test",
"lastModifiedDate" : 1414703168410,
"createdDate" : 1414703168410,
"messages" : [ ],
"threads" : [ ]
} ],
"messages" : [ ]
}
Run Code Online (Sandbox Code Playgroud)
杰克逊
如前所述,我能够使用解决问题
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id", scope=MyEntity.class)`
Run Code Online (Sandbox Code Playgroud)
对于此处建议的每个实体。该scope属性对于确保名称“id”在范围内是唯一的是必需的。实际上,如果没有该属性,正如您在此处scope看到的那样,它会抛出一个异常
com.fasterxml.jackson.databind.JsonMappingException: Already had POJO for id java.lang.String) [com.fasterxml.jackson.annotation.ObjectIdGenerator$IdKey@3372bb3f] (through reference chain: ParentEntity["children"]->java.util.ArrayList[0]->ChildEntity["id"])
...stacktrace...
Caused by: java.lang.IllegalStateException: Already had POJO for id (java.lang.String) [com.fasterxml.jackson.annotation.ObjectIdGenerator$IdKey@3372bb3f]
...stacktrace...
Run Code Online (Sandbox Code Playgroud)
格森
我仍然没有找到一种干净的方法来序列化循环依赖项。
| 归档时间: |
|
| 查看次数: |
8284 次 |
| 最近记录: |