Skip to content

Commit 0543bf1

Browse files
committed
Fix #81
1 parent af2414a commit 0543bf1

File tree

10 files changed

+643
-55
lines changed

10 files changed

+643
-55
lines changed

hibernate3/src/main/java/com/fasterxml/jackson/datatype/hibernate3/HibernateSerializerModifier.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ public JsonSerializer<?> modifySerializer(SerializationConfig config,
2929
@Override
3030
public JsonSerializer<?> modifyCollectionSerializer(SerializationConfig config,
3131
CollectionType valueType, BeanDescription beanDesc, JsonSerializer<?> serializer) {
32-
return new PersistentCollectionSerializer(serializer, _features, _sessionFactory);
32+
return new PersistentCollectionSerializer(valueType, serializer, _features, _sessionFactory);
3333
}
3434

3535
@Override
3636
public JsonSerializer<?> modifyMapSerializer(SerializationConfig config,
3737
MapType valueType, BeanDescription beanDesc, JsonSerializer<?> serializer) {
38-
return new PersistentCollectionSerializer(serializer, _features, _sessionFactory);
38+
return new PersistentCollectionSerializer(valueType, serializer, _features, _sessionFactory);
3939
}
4040
}

hibernate3/src/main/java/com/fasterxml/jackson/datatype/hibernate3/PersistentCollectionSerializer.java

Lines changed: 133 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,49 @@
11
package com.fasterxml.jackson.datatype.hibernate3;
22

33
import java.io.IOException;
4+
import java.util.Collection;
5+
import java.util.Map;
46

5-
import org.hibernate.FlushMode;
6-
import org.hibernate.Hibernate;
7-
import org.hibernate.Session;
8-
import org.hibernate.SessionFactory;
7+
import javax.persistence.*;
8+
9+
import org.hibernate.*;
910
import org.hibernate.collection.PersistentCollection;
1011

1112
import com.fasterxml.jackson.core.*;
1213
import com.fasterxml.jackson.databind.*;
14+
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
1315
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
1416
import com.fasterxml.jackson.databind.ser.*;
1517
import com.fasterxml.jackson.datatype.hibernate3.Hibernate3Module.Feature;
18+
1619
import org.hibernate.engine.PersistenceContext;
1720
import org.hibernate.engine.SessionFactoryImplementor;
1821
import org.hibernate.engine.SessionImplementor;
1922
import org.hibernate.impl.SessionFactoryImpl;
2023
import org.hibernate.transaction.JDBCTransactionFactory;
2124
import org.hibernate.transaction.TransactionFactory;
2225

23-
import javax.persistence.*;
24-
2526
/**
2627
* Wrapper serializer used to handle aspects of lazy loading that can be used
2728
* for Hibernate collection datatypes; which includes both <code>Collection</code>
2829
* and <code>Map</code> types (unlike in JDK).
2930
*/
3031
public class PersistentCollectionSerializer
31-
extends JsonSerializer<Object>
32-
implements ContextualSerializer
32+
extends ContainerSerializer<Object>
33+
implements ContextualSerializer, ResolvableSerializer
3334
{
35+
private static final long serialVersionUID = 1L; // since 2.7
36+
37+
/**
38+
* Type for which underlying serializer was created.
39+
*
40+
* @since 2.7
41+
*/
42+
protected final JavaType _originalType;
43+
44+
/**
45+
* Hibernate-module features set, if any.
46+
*/
3447
protected final int _features;
3548

3649
/**
@@ -48,13 +61,63 @@ public class PersistentCollectionSerializer
4861
*/
4962

5063
@SuppressWarnings("unchecked")
51-
public PersistentCollectionSerializer(JsonSerializer<?> serializer, int features, SessionFactory sessionFactory)
52-
{
64+
public PersistentCollectionSerializer(JavaType containerType,
65+
JsonSerializer<?> serializer, int features, SessionFactory sessionFactory) {
66+
super(containerType);
67+
_originalType = containerType;
5368
_serializer = (JsonSerializer<Object>) serializer;
5469
_features = features;
5570
_sessionFactory = sessionFactory;
5671
}
5772

73+
/**
74+
* @since 2.7
75+
*/
76+
@SuppressWarnings("unchecked")
77+
protected PersistentCollectionSerializer(PersistentCollectionSerializer base, JsonSerializer<?> serializer)
78+
{
79+
super(base);
80+
_originalType = base._originalType;
81+
_serializer = (JsonSerializer<Object>) serializer;
82+
_features = base._features;
83+
_sessionFactory = base._sessionFactory;
84+
}
85+
86+
protected PersistentCollectionSerializer _withSerializer(JsonSerializer<?> ser) {
87+
if (ser == _serializer) {
88+
return this;
89+
}
90+
return new PersistentCollectionSerializer(this, ser);
91+
}
92+
93+
// from `ContainerSerializer`
94+
@Override
95+
protected ContainerSerializer<?> _withValueTypeSerializer(TypeSerializer vts)
96+
{
97+
ContainerSerializer<?> ser0 = _containerSerializer();
98+
if (ser0 != null) {
99+
return _withSerializer(ser0.withValueTypeSerializer(vts));
100+
}
101+
// 03-Jan-2016, tatu: Not sure what to do here; most likely can not make it work without
102+
// knowing how to pass various calls... so in a way, should limit to only accepting
103+
// ContainerSerializers as delegates.
104+
return this;
105+
}
106+
107+
/*
108+
/**********************************************************************
109+
/* Contextualization
110+
/**********************************************************************
111+
*/
112+
113+
@Override
114+
public void resolve(SerializerProvider provider) throws JsonMappingException
115+
{
116+
if (_serializer instanceof ResolvableSerializer) {
117+
((ResolvableSerializer) _serializer).resolve(provider);
118+
}
119+
}
120+
58121
/**
59122
* We need to resolve actual serializer once we know the context; specifically
60123
* must know type of property being serialized.
@@ -74,19 +137,15 @@ public JsonSerializer<?> createContextual(SerializerProvider provider,
74137
if (!usesLazyLoading(property)) {
75138
return ser;
76139
}
77-
if (ser != _serializer) {
78-
return new PersistentCollectionSerializer(ser, _features, _sessionFactory);
79-
}
80-
return this;
140+
return _withSerializer(ser);
81141
}
82-
142+
83143
/*
84144
/**********************************************************************
85-
/* JsonSerializer impl
145+
/* JsonSerializer simple accessors, metadata
86146
/**********************************************************************
87147
*/
88148

89-
// since 2.3
90149
@Deprecated // since 2.5
91150
@Override
92151
public boolean isEmpty(Object value)
@@ -111,7 +170,56 @@ public boolean isEmpty(SerializerProvider provider, Object value)
111170
}
112171
return _serializer.isEmpty(provider, value);
113172
}
114-
173+
174+
@Override
175+
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
176+
throws JsonMappingException
177+
{
178+
_serializer.acceptJsonFormatVisitor(visitor, typeHint);
179+
}
180+
181+
/*
182+
/**********************************************************************
183+
/* ContainerSerializer methods
184+
/**********************************************************************
185+
*/
186+
187+
@Override
188+
public JavaType getContentType() {
189+
ContainerSerializer<?> ser = _containerSerializer();
190+
if (ser != null) {
191+
return ser.getContentType();
192+
}
193+
return _originalType.getContentType();
194+
}
195+
196+
@Override
197+
public JsonSerializer<?> getContentSerializer() {
198+
ContainerSerializer<?> ser = _containerSerializer();
199+
if (ser != null) {
200+
return ser.getContentSerializer();
201+
}
202+
// no idea, alas
203+
return null;
204+
}
205+
206+
@Override
207+
public boolean hasSingleElement(Object value) {
208+
if (value instanceof Collection<?>) {
209+
return ((Collection<?>) value).size() == 1;
210+
}
211+
if (value instanceof Map<?,?>) {
212+
return ((Map<?,?>) value).size() == 1;
213+
}
214+
return false;
215+
}
216+
217+
/*
218+
/**********************************************************************
219+
/* JsonSerializer, actual serialization
220+
/**********************************************************************
221+
*/
222+
115223
@Override
116224
public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider)
117225
throws IOException
@@ -164,6 +272,13 @@ public void serializeWithType(Object value, JsonGenerator jgen, SerializerProvid
164272
/**********************************************************************
165273
*/
166274

275+
protected ContainerSerializer<?> _containerSerializer() {
276+
if (_serializer instanceof ContainerSerializer) {
277+
return (ContainerSerializer<?>) _serializer;
278+
}
279+
return null;
280+
}
281+
167282
protected Object findLazyValue(PersistentCollection coll)
168283
{
169284
// If lazy-loaded, not yet loaded, may serialize as null?
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package com.fasterxml.jackson.datatype.hibernate3;
2+
3+
import java.util.*;
4+
5+
import com.fasterxml.jackson.annotation.*;
6+
import com.fasterxml.jackson.databind.ObjectMapper;
7+
8+
public class Polymorphic81Test extends BaseTest
9+
{
10+
static class TestLayout {
11+
public RecordFilters recordFilters = new RecordFilters();
12+
13+
public TestLayout addRecordFilter(AbstractRecordFilter recordFilter) {
14+
recordFilters.filters.add(recordFilter);
15+
return this;
16+
}
17+
}
18+
19+
static class RecordFilters implements RecordFilter {
20+
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
21+
@JsonSubTypes({
22+
@JsonSubTypes.Type(value = EmptyRecordFilter.class)
23+
// ,@JsonSubTypes.Type(value = RangeRecordFilter.class) }
24+
})
25+
public List<AbstractRecordFilter> filters = new ArrayList<AbstractRecordFilter>();
26+
}
27+
28+
public interface RecordFilter { }
29+
30+
static abstract class AbstractRecordFilter implements RecordFilter { }
31+
32+
@JsonTypeName(value="emptyRecordFilter")
33+
static class EmptyRecordFilter extends AbstractRecordFilter {
34+
Expression expr;
35+
36+
EmptyRecordFilter() {
37+
}
38+
39+
public EmptyRecordFilter(Expression expr) {
40+
this.expr = expr;
41+
}
42+
}
43+
44+
static class Expression {
45+
private String expression;
46+
47+
Expression() { }
48+
49+
public Expression(String expression) {
50+
this.expression = expression;
51+
}
52+
53+
public String getExpression() {
54+
return expression;
55+
}
56+
57+
public static Expression simpleFieldExpression(String field) {
58+
return new Expression("${" + field + "}");
59+
}
60+
}
61+
62+
public void testPolymorphic81() throws Exception
63+
{
64+
final ObjectMapper mapper = mapperWithModule(true);
65+
66+
final TestLayout layout = new TestLayout()
67+
.addRecordFilter(new EmptyRecordFilter(Expression.simpleFieldExpression("id")));
68+
69+
// uncomment the line below to see the problem
70+
// mapper.registerModule(new Hibernate4Module());
71+
72+
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(layout);
73+
// System.out.println("OUTPUT:\n"+json);
74+
75+
final TestLayout restoredLayout =
76+
mapper.readerFor(TestLayout.class).readValue(json);
77+
assertNotNull(restoredLayout);
78+
}
79+
}

hibernate4/src/main/java/com/fasterxml/jackson/datatype/hibernate4/HibernateSerializerModifier.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ public JsonSerializer<?> modifySerializer(SerializationConfig config,
3131
@Override
3232
public JsonSerializer<?> modifyCollectionSerializer(SerializationConfig config,
3333
CollectionType valueType, BeanDescription beanDesc, JsonSerializer<?> serializer) {
34-
return new PersistentCollectionSerializer(serializer, _features, _sessionFactory);
34+
return new PersistentCollectionSerializer(valueType, serializer, _features, _sessionFactory);
3535
}
3636

3737
@Override
3838
public JsonSerializer<?> modifyMapSerializer(SerializationConfig config,
3939
MapType valueType, BeanDescription beanDesc, JsonSerializer<?> serializer) {
40-
return new PersistentCollectionSerializer(serializer, _features, _sessionFactory);
40+
return new PersistentCollectionSerializer(valueType, serializer, _features, _sessionFactory);
4141
}
4242
}

0 commit comments

Comments
 (0)