Skip to content

Commit

Permalink
Fix #731
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Apr 2, 2015
1 parent fa1c2ff commit 119ddc9
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 14 deletions.
7 changes: 6 additions & 1 deletion release-notes/CREDITS
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,12 @@ Dylan Scott (dylanscott@github)
issue)
(2.5.2)

Dmitry Spikhalskiy (Spikhalskiy@github)
* Reported #731, suggested the way to fix it: XmlAdapter result marshaling error in
case of ValueType=Object
(2.5.3)

John Meyer (jpmeyer@github)
* Reported, contributed fix for #745: EnumDeserializer.deserializerForCreator fails
* Reported, contributed fix for #745: EnumDeserializer.deserializerForCreator() fails
when used to deserialize a Map key
(2.5.3)
2 changes: 2 additions & 0 deletions release-notes/VERSION
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Project: jackson-databind

2.5.3 (not yet released)

#731: XmlAdapter result marshaling error in case of ValueType=Object
(reported, debugged by Dmitry S)
#742: Allow deserialization of `null` Object Id (missing already allowed)
#744: Custom deserializer with parent object update failing
(reported by migel@github)
Expand Down
13 changes: 12 additions & 1 deletion src/main/java/com/fasterxml/jackson/databind/JavaType.java
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,17 @@ public boolean isConcrete() {
@Override
public boolean isMapLikeType() { return false; }

/**
* Convenience method, short-hand for
*<code>
* getRawClass() == Object.class
*</code>
* and used to figure if we basically have "untyped" type object.
*
* @since 2.5
*/
public final boolean isJavaLangObject() { return _class == Object.class; }

/**
* Accessor for checking whether handlers for dealing with values of
* this type should use static typing (as opposed to dynamic typing).
Expand All @@ -299,7 +310,7 @@ public boolean isConcrete() {
* @since 2.2
*/
public final boolean useStaticType() { return _asStatic; }

/*
/**********************************************************
/* Public API, type parameter access; pass-through
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ public JsonSerializer<Object> createSerializer(SerializerProvider prov,
// [#359]: explicitly check (again) for @JsonSerializer...
ser = findSerializerFromAnnotation(prov, beanDesc.getClassInfo());
}
if (ser == null) {
// [databind#731]: Should skip if nominally java.lang.Object
if (ser == null && !delegateType.isJavaLangObject()) {
ser = _createSerializer2(prov, delegateType, beanDesc, true);
}
return new StdDelegatingSerializer(conv, delegateType, ser);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,9 @@ protected JsonSerializer<Object> findConvertingSerializer(SerializerProvider pro
if (convDef != null) {
Converter<Object,Object> conv = provider.converterInstance(prop.getMember(), convDef);
JavaType delegateType = conv.getOutputType(provider.getTypeFactory());
JsonSerializer<?> ser = provider.findValueSerializer(delegateType, prop);
// [databind#731]: Should skip if nominally java.lang.Object
JsonSerializer<?> ser = delegateType.isJavaLangObject() ? null
: provider.findValueSerializer(delegateType, prop);
return new StdDelegatingSerializer(conv, delegateType, ser);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,20 @@ public JsonSerializer<?> createContextual(SerializerProvider provider, BeanPrope
if (delegateType == null) {
delegateType = _converter.getOutputType(provider.getTypeFactory());
}
delSer = provider.findValueSerializer(delegateType);
/* 02-Apr-2015, tatu: For "dynamic case", where type is only specified as
* java.lang.Object (or missing generic), [databind#731]
*/
if (!delegateType.isJavaLangObject()) {
delSer = provider.findValueSerializer(delegateType);
}
}
if (delSer instanceof ContextualSerializer) {
delSer = provider.handleSecondaryContextualization(delSer, property);
}
return (delSer == _delegateSerializer) ? this
: withDelegate(_converter, delegateType, delSer);
if (delSer == _delegateSerializer && delegateType == _delegateType) {
return this;
}
return withDelegate(_converter, delegateType, delSer);
}

/*
Expand Down Expand Up @@ -154,7 +161,12 @@ public void serialize(Object value, JsonGenerator gen, SerializerProvider provid
provider.defaultSerializeNull(gen);
return;
}
_delegateSerializer.serialize(delegateValue, gen, provider);
// 02-Apr-2015, tatu: As per [databind#731] may need to do dynamic lookup
JsonSerializer<Object> ser = _delegateSerializer;
if (ser == null) {
ser = _findSerializer(delegateValue, provider);
}
ser.serialize(delegateValue, gen, provider);
}

@Override
Expand All @@ -165,21 +177,31 @@ public void serializeWithType(Object value, JsonGenerator gen, SerializerProvide
* let's give it a chance?
*/
Object delegateValue = convertValue(value);
_delegateSerializer.serializeWithType(delegateValue, gen, provider, typeSer);
JsonSerializer<Object> ser = _delegateSerializer;
if (ser == null) {
ser = _findSerializer(value, provider);
}
ser.serializeWithType(delegateValue, gen, provider, typeSer);
}

@Override
@Deprecated // since 1.5
@Deprecated // since 2.5
public boolean isEmpty(Object value)
{
Object delegateValue = convertValue(value);
if (_delegateSerializer == null) { // best we can do for now, too costly to look up
return (value == null);
}
return _delegateSerializer.isEmpty(delegateValue);
}

@Override
public boolean isEmpty(SerializerProvider prov, Object value)
{
Object delegateValue = convertValue(value);
if (_delegateSerializer == null) { // best we can do for now, too costly to look up
return (value == null);
}
return _delegateSerializer.isEmpty(prov, delegateValue);
}

Expand Down Expand Up @@ -216,7 +238,10 @@ public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType t
/* 03-Sep-2012, tatu: Not sure if this can be made to really work
* properly... but for now, try this:
*/
_delegateSerializer.acceptJsonFormatVisitor(visitor, typeHint);
// 02-Apr-2015, tatu: For dynamic case, very little we can do
if (_delegateSerializer != null) {
_delegateSerializer.acceptJsonFormatVisitor(visitor, typeHint);
}
}

/*
Expand All @@ -239,4 +264,19 @@ public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType t
protected Object convertValue(Object value) {
return _converter.convert(value);
}

/**
* Helper method used for locating serializer to use in dynamic use case, where
* actual type value gets converted to is not specified beyond basic
* {@link java.lang.Object}, and where serializer needs to be located dynamically
* based on actual value type.
*
* @since 2.6
*/
protected JsonSerializer<Object> _findSerializer(Object value, SerializerProvider serializers)
throws JsonMappingException
{
// NOTE: will NOT call contextualization
return serializers.findValueSerializer(value.getClass());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,6 @@ protected JsonSerializer<?> findConvertingContentSerializer(SerializerProvider p
* when applying contextual content converter; this is not ideal way,
* but should work for most cases.
*/

final AnnotationIntrospector intr = provider.getAnnotationIntrospector();
if (intr != null && prop != null) {
AnnotatedMember m = prop.getMember();
Expand All @@ -259,7 +258,8 @@ protected JsonSerializer<?> findConvertingContentSerializer(SerializerProvider p
if (convDef != null) {
Converter<Object,Object> conv = provider.converterInstance(prop.getMember(), convDef);
JavaType delegateType = conv.getOutputType(provider.getTypeFactory());
if (existingSerializer == null) {
// [databind#731]: Should skip if nominally java.lang.Object
if (existingSerializer == null && !delegateType.hasRawClass(Object.class)) {
existingSerializer = provider.findValueSerializer(delegateType);
}
return new StdDelegatingSerializer(conv, delegateType, existingSerializer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,33 @@ public void serialize(Target a, JsonGenerator jsonGenerator, SerializerProvider
jsonGenerator.writeString("Target");
}
}


// [Issue#731]
public static class DummyBean {
public final int a, b;
public DummyBean(int v1, int v2) {
a = v1 * 2;
b = v2 * 2;
}
}

@JsonSerialize(converter = UntypedConvertingBeanConverter.class)
static class ConvertingBeanWithUntypedConverter {
public int x, y;
public ConvertingBeanWithUntypedConverter(int v1, int v2) {
x = v1;
y = v2;
}
}

static class UntypedConvertingBeanConverter extends StdConverter<ConvertingBeanWithUntypedConverter, Object>
{
@Override
public Object convert(ConvertingBeanWithUntypedConverter cb) {
return new DummyBean(cb.x, cb.y);
}
}

/*
/**********************************************************
/* Test methods
Expand Down Expand Up @@ -168,4 +194,12 @@ public void testIssue359() throws Exception {
String json = objectWriter().writeValueAsString(new Bean359());
assertEquals("{\"stuff\":[\"Target\"]}", json);
}

// [databind#731]: Problems converting from java.lang.Object ("unknown")
public void testIssue731() throws Exception
{
String json = objectWriter().writeValueAsString(new ConvertingBeanWithUntypedConverter(1, 2));
// must be {"a":2,"b":4}
assertEquals("{\"a\":2,\"b\":4}", json);
}
}

0 comments on commit 119ddc9

Please sign in to comment.