Как правильно преобразовать Список конкретных объектов в Gson?
Я работаю над проектом Spring MVC. Я использую Hibernate. Я хочу использовать AJAX с jQuery, чтобы получить некоторые JSON от моих контроллеров Spring. К сожалению, когда я применял методы 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);
}
Это мой класс Message
, который я использую в моем проекте Spring MVC с Hibernate:
@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>
не проксирован.
Ответы
Ответ 1
Я решил свою проблему. Предположение о объектах 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;
}
}
И все. Теперь я могу получить JSON в jQuery, используя AJAX правильно.
Ответ 2
Как упоминалось в комментариях @madhead, это происходит потому, что в зависимости от ситуации Hibernate создает прокси-серверы вокруг вашего объекта, который будет вызывать фактическую реализацию для некоторых методов и "инструмент" для других. Таким образом, "фактическим" типом ваших объектов является HibernateProxy. Вы можете получить доступ к своей реализации, используя код, подобный описанному здесь. В вашем случае вам придется вызывать метод "unproxy" для каждого элемента в вашем списке, помещая их в новый список.
Ответ 3
Хотя довольно старый, чтобы ответить, я думаю, просто создав DTO для полей Message with String, вы решите цель.