diff --git a/hibernate4/src/main/java/com/fasterxml/jackson/datatype/hibernate4/HibernateProxySerializer.java b/hibernate4/src/main/java/com/fasterxml/jackson/datatype/hibernate4/HibernateProxySerializer.java index f570a8bf..9d2d59f5 100644 --- a/hibernate4/src/main/java/com/fasterxml/jackson/datatype/hibernate4/HibernateProxySerializer.java +++ b/hibernate4/src/main/java/com/fasterxml/jackson/datatype/hibernate4/HibernateProxySerializer.java @@ -18,6 +18,7 @@ import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.ContextualSerializer; import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap; +import com.fasterxml.jackson.databind.util.NameTransformer; import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionImplementor; @@ -47,6 +48,7 @@ public class HibernateProxySerializer protected final boolean _serializeIdentifier; protected final boolean _nullMissingEntities; protected final Mapping _mapping; + protected final NameTransformer _unwrapper; /** * For efficient serializer lookup, let's use this; most @@ -62,35 +64,56 @@ public class HibernateProxySerializer public HibernateProxySerializer(boolean forceLazyLoading) { - this(forceLazyLoading, false, false, null, null); + this(forceLazyLoading, false, false, null, null, null); } public HibernateProxySerializer(boolean forceLazyLoading, boolean serializeIdentifier) { - this(forceLazyLoading, serializeIdentifier, false, null, null); + this(forceLazyLoading, serializeIdentifier, false, null, null, null); } public HibernateProxySerializer(boolean forceLazyLoading, boolean serializeIdentifier, Mapping mapping) { - this(forceLazyLoading, serializeIdentifier, false, mapping, null); + this(forceLazyLoading, serializeIdentifier, false, mapping, null, null); } public HibernateProxySerializer(boolean forceLazyLoading, boolean serializeIdentifier, boolean nullMissingEntities, Mapping mapping) { - this(forceLazyLoading, serializeIdentifier, nullMissingEntities, mapping, null); + this(forceLazyLoading, serializeIdentifier, nullMissingEntities, mapping, null, null); } public HibernateProxySerializer(boolean forceLazyLoading, boolean serializeIdentifier, boolean nullMissingEntities, Mapping mapping, BeanProperty property) { + this(forceLazyLoading, serializeIdentifier, nullMissingEntities, mapping, property, null); + } + + + protected HibernateProxySerializer(boolean forceLazyLoading, boolean serializeIdentifier, boolean nullMissingEntities, Mapping mapping, + BeanProperty property, NameTransformer unwrapper) { _forceLazyLoading = forceLazyLoading; _serializeIdentifier = serializeIdentifier; _nullMissingEntities = nullMissingEntities; _mapping = mapping; _dynamicSerializers = PropertySerializerMap.emptyForProperties(); _property = property; + _unwrapper = unwrapper; } @Override public JsonSerializer createContextual(SerializerProvider prov, BeanProperty property) { return new HibernateProxySerializer(this._forceLazyLoading, _serializeIdentifier, _nullMissingEntities, - _mapping, property); + _mapping, property, _unwrapper); + } + + @Override + public JsonSerializer unwrappingSerializer( + final NameTransformer unwrapper) + { + return new HibernateProxySerializer(_forceLazyLoading, _serializeIdentifier, _nullMissingEntities, + _mapping, _property, unwrapper == null ? NameTransformer.NOP : unwrapper); + } + + @Override + public boolean isUnwrappingSerializer() + { + return _unwrapper != null; } /* @@ -174,6 +197,10 @@ protected JsonSerializer findSerializer(SerializerProvider provider, Obj if (_dynamicSerializers != result.map) { _dynamicSerializers = result.map; } + if (_unwrapper != null) + { + return result.serializer.unwrappingSerializer(_unwrapper); + } return result.serializer; } diff --git a/hibernate4/src/test/java/com/fasterxml/jackson/datatype/hibernate4/UnwrappedTest.java b/hibernate4/src/test/java/com/fasterxml/jackson/datatype/hibernate4/UnwrappedTest.java new file mode 100644 index 00000000..da82f260 --- /dev/null +++ b/hibernate4/src/test/java/com/fasterxml/jackson/datatype/hibernate4/UnwrappedTest.java @@ -0,0 +1,64 @@ +package com.fasterxml.jackson.datatype.hibernate4; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonUnwrapped; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.hibernate4.data.Customer; +import com.fasterxml.jackson.datatype.hibernate4.data.Product; +import org.hibernate.Hibernate; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import java.util.Map; + +/** + * Unit test for [#97] + */ +public class UnwrappedTest extends BaseTest +{ + static class HasUnwrapped + { + private final T content; + + @JsonCreator + public HasUnwrapped(T content) + { + this.content = content; + } + + @JsonUnwrapped + public T getContent() + { + return content; + } + } + + public void testSimpleUnwrapped() throws JsonProcessingException + { + EntityManagerFactory emf = Persistence.createEntityManagerFactory("persistenceUnit"); + try { + EntityManager em = emf.createEntityManager(); + + ObjectMapper mapper = mapperWithModule(true); + + Customer customer = em.find(Customer.class, 500); + Product product = customer.getMissingProduct(); + assertFalse(Hibernate.isInitialized(product)); + + String json = mapper.writeValueAsString(new HasUnwrapped<>(product)); + + assertTrue(Hibernate.isInitialized(product)); + assertNotNull(json); + HasUnwrapped deserialized = mapper.readValue(json, new TypeReference>(){}); + assertTrue(deserialized != null); + assertTrue(deserialized.getContent() != null); + assertTrue(deserialized.getContent().getProductCode() != null); + + } finally { + emf.close(); + } + } +} diff --git a/hibernate5/src/main/java/com/fasterxml/jackson/datatype/hibernate5/HibernateProxySerializer.java b/hibernate5/src/main/java/com/fasterxml/jackson/datatype/hibernate5/HibernateProxySerializer.java index 6245ad84..e2ea3e79 100644 --- a/hibernate5/src/main/java/com/fasterxml/jackson/datatype/hibernate5/HibernateProxySerializer.java +++ b/hibernate5/src/main/java/com/fasterxml/jackson/datatype/hibernate5/HibernateProxySerializer.java @@ -18,6 +18,7 @@ import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.ContextualSerializer; import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap; +import com.fasterxml.jackson.databind.util.NameTransformer; import org.hibernate.engine.spi.Mapping; import org.hibernate.engine.spi.SessionFactoryImplementor; @@ -48,6 +49,7 @@ public class HibernateProxySerializer protected final boolean _serializeIdentifier; protected final boolean _nullMissingEntities; protected final Mapping _mapping; + protected final NameTransformer _unwrapper; /** * For efficient serializer lookup, let's use this; most @@ -63,36 +65,57 @@ public class HibernateProxySerializer public HibernateProxySerializer(boolean forceLazyLoading) { - this(forceLazyLoading, false, false, null, null); + this(forceLazyLoading, false, false, null, null, null); } public HibernateProxySerializer(boolean forceLazyLoading, boolean serializeIdentifier) { - this(forceLazyLoading, serializeIdentifier, false, null, null); + this(forceLazyLoading, serializeIdentifier, false, null, null, null); } public HibernateProxySerializer(boolean forceLazyLoading, boolean serializeIdentifier, Mapping mapping) { - this(forceLazyLoading, serializeIdentifier, false, mapping, null); + this(forceLazyLoading, serializeIdentifier, false, mapping, null, null); } public HibernateProxySerializer(boolean forceLazyLoading, boolean serializeIdentifier, boolean nullMissingEntities, Mapping mapping) { - this(forceLazyLoading, serializeIdentifier, nullMissingEntities, mapping, null); + this(forceLazyLoading, serializeIdentifier, nullMissingEntities, mapping, null, null); } public HibernateProxySerializer(boolean forceLazyLoading, boolean serializeIdentifier, boolean nullMissingEntities, Mapping mapping, - BeanProperty property) { + BeanProperty property) { + this(forceLazyLoading, serializeIdentifier, nullMissingEntities, mapping, property, null); + } + + + protected HibernateProxySerializer(boolean forceLazyLoading, boolean serializeIdentifier, boolean nullMissingEntities, Mapping mapping, + BeanProperty property, NameTransformer unwrapper) { _forceLazyLoading = forceLazyLoading; _serializeIdentifier = serializeIdentifier; _nullMissingEntities = nullMissingEntities; _mapping = mapping; _dynamicSerializers = PropertySerializerMap.emptyForProperties(); _property = property; + _unwrapper = unwrapper; } @Override public JsonSerializer createContextual(SerializerProvider prov, BeanProperty property) { return new HibernateProxySerializer(this._forceLazyLoading, _serializeIdentifier, _nullMissingEntities, - _mapping, property); - } + _mapping, property, _unwrapper); + } + + @Override + public JsonSerializer unwrappingSerializer( + final NameTransformer unwrapper) + { + return new HibernateProxySerializer(_forceLazyLoading, _serializeIdentifier, _nullMissingEntities, + _mapping, _property, unwrapper == null ? NameTransformer.NOP : unwrapper); + } + + @Override + public boolean isUnwrappingSerializer() + { + return _unwrapper != null; + } /* /********************************************************************** @@ -175,6 +198,10 @@ protected JsonSerializer findSerializer(SerializerProvider provider, Obj if (_dynamicSerializers != result.map) { _dynamicSerializers = result.map; } + if (_unwrapper != null) + { + return result.serializer.unwrappingSerializer(_unwrapper); + } return result.serializer; } diff --git a/hibernate5/src/test/java/com/fasterxml/jackson/datatype/hibernate5/UnwrappedTest.java b/hibernate5/src/test/java/com/fasterxml/jackson/datatype/hibernate5/UnwrappedTest.java new file mode 100644 index 00000000..68153ab8 --- /dev/null +++ b/hibernate5/src/test/java/com/fasterxml/jackson/datatype/hibernate5/UnwrappedTest.java @@ -0,0 +1,64 @@ +package com.fasterxml.jackson.datatype.hibernate5; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonUnwrapped; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.hibernate5.data.Customer; +import com.fasterxml.jackson.datatype.hibernate5.data.Product; +import org.hibernate.Hibernate; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import java.util.Map; + +/** + * Unit test for [#97] + */ +public class UnwrappedTest extends BaseTest +{ + static class HasUnwrapped + { + private final T content; + + @JsonCreator + public HasUnwrapped(T content) + { + this.content = content; + } + + @JsonUnwrapped + public T getContent() + { + return content; + } + } + + public void testSimpleUnwrapped() throws JsonProcessingException + { + EntityManagerFactory emf = Persistence.createEntityManagerFactory("persistenceUnit"); + try { + EntityManager em = emf.createEntityManager(); + + ObjectMapper mapper = mapperWithModule(true); + + Customer customer = em.find(Customer.class, 500); + Product product = customer.getMissingProduct(); + assertFalse(Hibernate.isInitialized(product)); + + String json = mapper.writeValueAsString(new HasUnwrapped<>(product)); + + assertTrue(Hibernate.isInitialized(product)); + assertNotNull(json); + HasUnwrapped deserialized = mapper.readValue(json, new TypeReference>(){}); + assertTrue(deserialized != null); + assertTrue(deserialized.getContent() != null); + assertTrue(deserialized.getContent().getProductCode() != null); + + } finally { + emf.close(); + } + } +}