如何正确地将特定对象列表转换为 Gson?
Posted
技术标签:
【中文标题】如何正确地将特定对象列表转换为 Gson?【英文标题】:How to properly convert List of specific objects to Gson? 【发布时间】:2012-07-16 02:44:32 【问题描述】:我正在开发 Spring MVC 项目。我正在使用休眠。我想使用 AJAX 和 jQuery 从我的 Spring 控制器中获取一些 JSON。不幸的是,当我在我的应用程序中实现 Gson
方法时,我遇到了一个错误:
java.lang.UnsupportedOperationException: Attempted to serialize java.lang.Class:
org.hibernate.proxy.HibernateProxy. Forgot to register a type adapter?
我必须使用哪个适配器以及以何种方式使用?错误发生在方法的最后一行:
public String messagesToJson(List<Message> messages)
Gson gson = new Gson();
List<Message> synchronizedMessages = Collections.synchronizedList(messages);
return gson.toJson(synchronizedMessages, ArrayList.class);
这是我在带有 Hibernate 的 Spring MVC 项目中使用的 Message
类:
@Entity
@Table(name = "MESSAGES", schema = "PUBLIC", catalog = "PUBLIC")
public class Message implements java.io.Serializable
private static final long serialVersionUID = 1L;
private int messageId;
private User users;
private String message;
private Date date;
//Constructor, getters, setters, toString
编辑
我想知道:我的 Message
对象是代理还是整个 List<Message>
?我以这种方式获取消息列表:
public List<Message> findAllUserMessages(String username)
Query query = entityManager.createQuery("from Message where username = :username order by date desc")
.setParameter("username", username);
@SuppressWarnings("unchecked")
List<Message> messages = query.getResultList();
return messages;
编辑 2
不,我的 List<Message>
对象没有被代理。
【问题讨论】:
这可能是因为 hibernate 为您的对象创建了代理。因此参数List<Message> messages
无法处理该代理。正如您从堆栈跟踪中看到的那样,您正在尝试序列化org.hibernate.proxy.HibernateProxy
。也许您可以在运行时将cglib
与字节码操作一起使用以避免创建代理。
您应该将 Hibernate 对象映射到常规对象。
我必须简单地创建类似于 Hibernate 对象但没有注释的 POJO 类? @madhead 但是在我看来使用cglib
有点过头了。
仅供参考,如果List<Message>
被代理,则它不是HibernateProxy
的实例,而是PersistentCollection
的实例。当心你正在测试的东西;)
【参考方案1】:
虽然回答起来已经很老了,但我想只需为带有字符串字段的消息创建一个 DTO 就可以解决这个问题。
【讨论】:
【参考方案2】:我已经解决了我的问题。关于HibernateProxy
对象的假设似乎很有可能。然而,当我仔细阅读我的错误时,一切都开始正常工作了。最后我以这种方式注册了类型适配器:
public String messagesToJson(List<Message> messages)
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.registerTypeAdapter(Message.class, new MessageAdapter()).create();
return gson.toJson(messages);
我的任何MessageAdapter
类看起来像:
public class MessageAdapter implements JsonSerializer<Message>
@Override
public JsonElement serialize(Message message, Type type, JsonSerializationContext jsc)
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("message_id", message.getMessageId());
jsonObject.addProperty("message", message.getMessage());
jsonObject.addProperty("user", message.getUsers().getUsername());
jsonObject.addProperty("date", message.getDate().toString());
return jsonObject;
仅此而已。现在我可以正确使用 AJAX 在 jQuery 中获取 JSON。
【讨论】:
非常感谢 woyaru.. 我有类似的问题,但通过创建自定义 JsonSerializer 解决了这个问题。 :)【参考方案3】:正如@madhead 在 cmets 中提到的那样,发生这种情况是因为,根据具体情况,Hibernate 在您的对象周围创建代理,这将调用某些方法的实际实现,并为其他方法调用“仪器化”。因此,对象的“实际”类型是 HibernateProxy。您可以使用类似于here 描述的代码来访问您的实现。在您的情况下,您必须为列表中的每个项目调用“unproxy”方法,将它们放入一个新列表中。
【讨论】:
不幸的是,我仍然遇到同样的错误。我已经在我的项目中实现了unproxy
方法,例如您建议我。
我意识到我的对象不是HibernateProxy
的实例。所以unproxy
方法在我的情况下什么都不做。我的意思是在这种情况下if (entity != null && entity instanceof HibernateProxy)
结果是假的。以上是关于如何正确地将特定对象列表转换为 Gson?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 ASP Net Core Web API 上正确地将列表转换为 IQueryable
Kotlin 使用 Gson 将 json 字符串转换为对象列表