package fr.openwide.core.rest.jersey2.util.jackson.serializer;
import java.io.IOException;
import org.hibernate.proxy.HibernateProxy;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.ser.BeanSerializer;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import com.fasterxml.jackson.databind.ser.impl.ObjectIdWriter;
import fr.openwide.core.jpa.util.HibernateUtils;
/**
* BeanSerializerModifier that correctly handles Hibernate proxies.
*/
public class HibernateBeanSerializerModifier extends BeanSerializerModifier {
@Override
public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc,
JsonSerializer<?> serializer) {
if (serializer instanceof BeanSerializer) {
return new BeanSerializerWrapper((BeanSerializer) serializer);
} else {
return serializer;
}
}
public static class BeanSerializerWrapper extends BeanSerializer {
private static final long serialVersionUID = 1L;
private final BeanSerializer serializer;
protected BeanSerializerWrapper(BeanSerializer src) {
super(src);
this.serializer = src;
}
protected BeanSerializerWrapper(BeanSerializerWrapper src, ObjectIdWriter objectIdWriter) {
super(src.serializer, objectIdWriter);
this.serializer = src;
}
protected BeanSerializerWrapper(BeanSerializerWrapper src, String[] toIgnore) {
super(src.serializer, toIgnore);
this.serializer = src;
}
@Override
public BeanSerializerWrapper withObjectIdWriter(ObjectIdWriter objectIdWriter) {
return new BeanSerializerWrapper(this, objectIdWriter);
}
@Override
protected BeanSerializerWrapper withIgnorals(String[] toIgnore) {
return new BeanSerializerWrapper(this, toIgnore);
}
private <T> T unwrapBean(T bean) {
// Pour serializeFields* :
// C'est une étape non nécessaire car le serializerFactory utilisé en amont a modifié le type
// d'introspection. La liste des propriétés sera donc la bonne.
// On réalise quand même l'unwrapping pour plus de cohérence.
// Pour serializeWithType : absolument nécessaire, car la sérialisation du type ne prend pas du tout
// en compte ce qu'on a fait dans serializerFactory.
// pour les IObjetTouristiqueLinkedReference, on n'unwrappe pas le bean car on le type statiquement et on
// se contente de l'identifiant.
if (bean instanceof HibernateProxy) {
bean = HibernateUtils.unwrap(bean);
}
return bean;
}
@Override
protected void serializeFieldsFiltered(Object bean, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException {
if (bean == null) {
return;
} else {
Object object = unwrapBean(bean);
super.serializeFieldsFiltered(object, jgen, provider);
}
}
@Override
protected void serializeFields(Object bean, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonGenerationException {
if (bean == null) {
return;
} else {
Object object = unwrapBean(bean);
super.serializeFields(object, jgen, provider);
}
}
@Override
public void serializeWithType(Object bean, JsonGenerator jgen, SerializerProvider provider,
TypeSerializer typeSer) throws IOException, JsonGenerationException {
if (bean == null) {
return;
} else {
Object object = unwrapBean(bean);
super.serializeWithType(object, jgen, provider, typeSer);
}
}
}
}