Skip to content

Commit

Permalink
Fix #81
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Jan 4, 2016
1 parent af2414a commit 0543bf1
Show file tree
Hide file tree
Showing 10 changed files with 643 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ public JsonSerializer<?> modifySerializer(SerializationConfig config,
@Override
public JsonSerializer<?> modifyCollectionSerializer(SerializationConfig config,
CollectionType valueType, BeanDescription beanDesc, JsonSerializer<?> serializer) {
return new PersistentCollectionSerializer(serializer, _features, _sessionFactory);
return new PersistentCollectionSerializer(valueType, serializer, _features, _sessionFactory);
}

@Override
public JsonSerializer<?> modifyMapSerializer(SerializationConfig config,
MapType valueType, BeanDescription beanDesc, JsonSerializer<?> serializer) {
return new PersistentCollectionSerializer(serializer, _features, _sessionFactory);
return new PersistentCollectionSerializer(valueType, serializer, _features, _sessionFactory);
}
}
Original file line number Diff line number Diff line change
@@ -1,36 +1,49 @@
package com.fasterxml.jackson.datatype.hibernate3;

import java.io.IOException;
import java.util.Collection;
import java.util.Map;

import org.hibernate.FlushMode;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import javax.persistence.*;

import org.hibernate.*;
import org.hibernate.collection.PersistentCollection;

import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.ser.*;
import com.fasterxml.jackson.datatype.hibernate3.Hibernate3Module.Feature;

import org.hibernate.engine.PersistenceContext;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.impl.SessionFactoryImpl;
import org.hibernate.transaction.JDBCTransactionFactory;
import org.hibernate.transaction.TransactionFactory;

import javax.persistence.*;

/**
* Wrapper serializer used to handle aspects of lazy loading that can be used
* for Hibernate collection datatypes; which includes both <code>Collection</code>
* and <code>Map</code> types (unlike in JDK).
*/
public class PersistentCollectionSerializer
extends JsonSerializer<Object>
implements ContextualSerializer
extends ContainerSerializer<Object>
implements ContextualSerializer, ResolvableSerializer
{
private static final long serialVersionUID = 1L; // since 2.7

/**
* Type for which underlying serializer was created.
*
* @since 2.7
*/
protected final JavaType _originalType;

/**
* Hibernate-module features set, if any.
*/
protected final int _features;

/**
Expand All @@ -48,13 +61,63 @@ public class PersistentCollectionSerializer
*/

@SuppressWarnings("unchecked")
public PersistentCollectionSerializer(JsonSerializer<?> serializer, int features, SessionFactory sessionFactory)
{
public PersistentCollectionSerializer(JavaType containerType,
JsonSerializer<?> serializer, int features, SessionFactory sessionFactory) {
super(containerType);
_originalType = containerType;
_serializer = (JsonSerializer<Object>) serializer;
_features = features;
_sessionFactory = sessionFactory;
}

/**
* @since 2.7
*/
@SuppressWarnings("unchecked")
protected PersistentCollectionSerializer(PersistentCollectionSerializer base, JsonSerializer<?> serializer)
{
super(base);
_originalType = base._originalType;
_serializer = (JsonSerializer<Object>) serializer;
_features = base._features;
_sessionFactory = base._sessionFactory;
}

protected PersistentCollectionSerializer _withSerializer(JsonSerializer<?> ser) {
if (ser == _serializer) {
return this;
}
return new PersistentCollectionSerializer(this, ser);
}

// from `ContainerSerializer`
@Override
protected ContainerSerializer<?> _withValueTypeSerializer(TypeSerializer vts)
{
ContainerSerializer<?> ser0 = _containerSerializer();
if (ser0 != null) {
return _withSerializer(ser0.withValueTypeSerializer(vts));
}
// 03-Jan-2016, tatu: Not sure what to do here; most likely can not make it work without
// knowing how to pass various calls... so in a way, should limit to only accepting
// ContainerSerializers as delegates.
return this;
}

/*
/**********************************************************************
/* Contextualization
/**********************************************************************
*/

@Override
public void resolve(SerializerProvider provider) throws JsonMappingException
{
if (_serializer instanceof ResolvableSerializer) {
((ResolvableSerializer) _serializer).resolve(provider);
}
}

/**
* We need to resolve actual serializer once we know the context; specifically
* must know type of property being serialized.
Expand All @@ -74,19 +137,15 @@ public JsonSerializer<?> createContextual(SerializerProvider provider,
if (!usesLazyLoading(property)) {
return ser;
}
if (ser != _serializer) {
return new PersistentCollectionSerializer(ser, _features, _sessionFactory);
}
return this;
return _withSerializer(ser);
}

/*
/**********************************************************************
/* JsonSerializer impl
/* JsonSerializer simple accessors, metadata
/**********************************************************************
*/

// since 2.3
@Deprecated // since 2.5
@Override
public boolean isEmpty(Object value)
Expand All @@ -111,7 +170,56 @@ public boolean isEmpty(SerializerProvider provider, Object value)
}
return _serializer.isEmpty(provider, value);
}


@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
_serializer.acceptJsonFormatVisitor(visitor, typeHint);
}

/*
/**********************************************************************
/* ContainerSerializer methods
/**********************************************************************
*/

@Override
public JavaType getContentType() {
ContainerSerializer<?> ser = _containerSerializer();
if (ser != null) {
return ser.getContentType();
}
return _originalType.getContentType();
}

@Override
public JsonSerializer<?> getContentSerializer() {
ContainerSerializer<?> ser = _containerSerializer();
if (ser != null) {
return ser.getContentSerializer();
}
// no idea, alas
return null;
}

@Override
public boolean hasSingleElement(Object value) {
if (value instanceof Collection<?>) {
return ((Collection<?>) value).size() == 1;
}
if (value instanceof Map<?,?>) {
return ((Map<?,?>) value).size() == 1;
}
return false;
}

/*
/**********************************************************************
/* JsonSerializer, actual serialization
/**********************************************************************
*/

@Override
public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider)
throws IOException
Expand Down Expand Up @@ -164,6 +272,13 @@ public void serializeWithType(Object value, JsonGenerator jgen, SerializerProvid
/**********************************************************************
*/

protected ContainerSerializer<?> _containerSerializer() {
if (_serializer instanceof ContainerSerializer) {
return (ContainerSerializer<?>) _serializer;
}
return null;
}

protected Object findLazyValue(PersistentCollection coll)
{
// If lazy-loaded, not yet loaded, may serialize as null?
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.fasterxml.jackson.datatype.hibernate3;

import java.util.*;

import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Polymorphic81Test extends BaseTest
{
static class TestLayout {
public RecordFilters recordFilters = new RecordFilters();

public TestLayout addRecordFilter(AbstractRecordFilter recordFilter) {
recordFilters.filters.add(recordFilter);
return this;
}
}

static class RecordFilters implements RecordFilter {
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
@JsonSubTypes({
@JsonSubTypes.Type(value = EmptyRecordFilter.class)
// ,@JsonSubTypes.Type(value = RangeRecordFilter.class) }
})
public List<AbstractRecordFilter> filters = new ArrayList<AbstractRecordFilter>();
}

public interface RecordFilter { }

static abstract class AbstractRecordFilter implements RecordFilter { }

@JsonTypeName(value="emptyRecordFilter")
static class EmptyRecordFilter extends AbstractRecordFilter {
Expression expr;

EmptyRecordFilter() {
}

public EmptyRecordFilter(Expression expr) {
this.expr = expr;
}
}

static class Expression {
private String expression;

Expression() { }

public Expression(String expression) {
this.expression = expression;
}

public String getExpression() {
return expression;
}

public static Expression simpleFieldExpression(String field) {
return new Expression("${" + field + "}");
}
}

public void testPolymorphic81() throws Exception
{
final ObjectMapper mapper = mapperWithModule(true);

final TestLayout layout = new TestLayout()
.addRecordFilter(new EmptyRecordFilter(Expression.simpleFieldExpression("id")));

// uncomment the line below to see the problem
// mapper.registerModule(new Hibernate4Module());

String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(layout);
// System.out.println("OUTPUT:\n"+json);

final TestLayout restoredLayout =
mapper.readerFor(TestLayout.class).readValue(json);
assertNotNull(restoredLayout);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ public JsonSerializer<?> modifySerializer(SerializationConfig config,
@Override
public JsonSerializer<?> modifyCollectionSerializer(SerializationConfig config,
CollectionType valueType, BeanDescription beanDesc, JsonSerializer<?> serializer) {
return new PersistentCollectionSerializer(serializer, _features, _sessionFactory);
return new PersistentCollectionSerializer(valueType, serializer, _features, _sessionFactory);
}

@Override
public JsonSerializer<?> modifyMapSerializer(SerializationConfig config,
MapType valueType, BeanDescription beanDesc, JsonSerializer<?> serializer) {
return new PersistentCollectionSerializer(serializer, _features, _sessionFactory);
return new PersistentCollectionSerializer(valueType, serializer, _features, _sessionFactory);
}
}
Loading

0 comments on commit 0543bf1

Please sign in to comment.