摘要: Attempted to serialize java.lang.Class: org.hibernate.proxy.HibernateProxy. Forgot to register a type adapter?
使用Gson转换Hibernate对象遇到一个问题,当对象的Lazy加载的,就会出现上面的错误。处理方式摘抄自网上,留存一份以后自己看。
-
/**
-
* This TypeAdapter unproxies Hibernate proxied objects, and serializes them
-
* through the registered (or default) TypeAdapter of the base class.
-
*/
-
public class HibernateProxyTypeAdapter extends TypeAdapter<HibernateProxy> {
-
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
-
@Override
-
@SuppressWarnings("unchecked")
-
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
-
return (HibernateProxy.class.isAssignableFrom(type.getRawType()) ? (TypeAdapter<T>) new HibernateProxyTypeAdapter(gson) : null);
-
}
-
};
-
private final Gson context;
-
private HibernateProxyTypeAdapter(Gson context) {
-
this.context = context;
-
}
-
@Override
-
public HibernateProxy read(JsonReader in) throws IOException {
-
throw new UnsupportedOperationException("Not supported");
-
}
-
@SuppressWarnings({"rawtypes", "unchecked"})
-
@Override
-
public void write(JsonWriter out, HibernateProxy value) throws IOException {
-
if (value == null) {
-
out.nullValue();
-
return;
-
}
-
// Retrieve the original (not proxy) class
-
Class<?> baseType = Hibernate.getClass(value);
-
// Get the TypeAdapter of the original class, to delegate the serialization
-
TypeAdapter delegate = context.getAdapter(TypeToken.get(baseType));
-
// Get a filled instance of the original class
-
Object unproxiedValue = ((HibernateProxy) value).getHibernateLazyInitializer()
-
.getImplementation();
-
// Serialize the value
-
delegate.write(out, unproxiedValue);
-
}
-
}
实现上面的类,然后就是使用:
-
GsonBuilder b = new GsonBuilder();
-
...
-
b.registerTypeAdapterFactory(HibernateProxyTypeAdapter.FACTORY);
-
...
-
Gson gson = b.create();
解释,只是看不懂。
GSON contains a number of TypeAdapterFactory
implementations, for various types (primitive types, common types like String
or Date
, lists, arrays...). Each factory is asked if it is able to serialize a certain Java type (the parameter to create
is a TypeToken
instead of a Class
in order to capture possible information about generic types, which Class
does not have). If the factory is able to serialize/deserialize a type, it responds with a TypeAdapter
instance; otherwise it responds with null
.
HibernateProxyTypeAdapter.FACTORY
verifies whether type implements HibernateProxy
; in that case, it returns an instance of HibernateProxyTypeAdapter
for serialization. The write
method is called when an actual object has to be serialized; the adapter extracts the original type of the underlying object, and asks GSON for the standard TypeAdapter
for the original type, which generally is a ReflectiveTypeAdapter
.
Then it retrieves an instance of the original class, instead of directly using the proxy. This is necessary because ReflectiveTypeAdapter
accesses directly to fields, instead of using getters; accessing to the fields of a proxied object does not work, and is a classical Hibernate pitfall.
As a possible performance improvement, the delegate TypeAdapter
should be acquired in the create
method. I found out that calling getSuperclass()
on the proxy Class
appears to yield the original base class.
--------------------- 本文来自 xspwz123 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/xspwz123/article/details/71425545?utm_source=copy