Skip to content

Commit 7b5694b

Browse files
committed
Refactoring to try to (eventually) solve #357; still problematic wrt contextualization, infinite recursion
1 parent 1861b09 commit 7b5694b

File tree

5 files changed

+82
-33
lines changed

5 files changed

+82
-33
lines changed

src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java

Lines changed: 59 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -425,8 +425,7 @@ public abstract WritableObjectId findObjectId(Object forPojo,
425425
* finding any serializer
426426
*/
427427
@SuppressWarnings("unchecked")
428-
public JsonSerializer<Object> findValueSerializer(Class<?> valueType,
429-
BeanProperty property)
428+
public JsonSerializer<Object> findValueSerializer(Class<?> valueType, BeanProperty property)
430429
throws JsonMappingException
431430
{
432431
// Fast lookup from local lookup thingy works?
@@ -440,11 +439,7 @@ public JsonSerializer<Object> findValueSerializer(Class<?> valueType,
440439
if (ser == null) {
441440
// If neither, must create
442441
ser = _createAndCacheUntypedSerializer(valueType);
443-
// Not found? Must use the unknown type serializer
444-
/* Couldn't create? Need to return the fallback serializer, which
445-
* most likely will report an error: but one question is whether
446-
* we should cache it?
447-
*/
442+
// Not found? Must use the unknown type serializer, which will report error later on
448443
if (ser == null) {
449444
ser = getUnknownTypeSerializer(valueType);
450445
// Should this be added to lookups?
@@ -474,22 +469,14 @@ public JsonSerializer<Object> findValueSerializer(Class<?> valueType,
474469
public JsonSerializer<Object> findValueSerializer(JavaType valueType, BeanProperty property)
475470
throws JsonMappingException
476471
{
477-
// Fast lookup from local lookup thingy works?
472+
// (see comments from above method)
478473
JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType);
479474
if (ser == null) {
480-
// If not, maybe shared map already has it?
481475
ser = _serializerCache.untypedValueSerializer(valueType);
482476
if (ser == null) {
483-
// If neither, must create
484477
ser = _createAndCacheUntypedSerializer(valueType);
485-
// Not found? Must use the unknown type serializer
486-
/* Couldn't create? Need to return the fallback serializer, which
487-
* most likely will report an error: but one question is whether
488-
* we should cache it?
489-
*/
490478
if (ser == null) {
491479
ser = getUnknownTypeSerializer(valueType.getRawClass());
492-
// Should this be added to lookups?
493480
if (CACHE_UNKNOWN_MAPPINGS) {
494481
_serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this);
495482
}
@@ -500,6 +487,62 @@ public JsonSerializer<Object> findValueSerializer(JavaType valueType, BeanProper
500487
return (JsonSerializer<Object>) handleSecondaryContextualization(ser, property);
501488
}
502489

490+
/**
491+
* Method variant used when we do NOT want contextualization to happen; it will need
492+
* to be handled at a later point, but caller wants to be able to do that
493+
* as needed; sometimes to avoid infinite loops
494+
*
495+
* @since 2.5
496+
*/
497+
public JsonSerializer<Object> findValueSerializer(Class<?> valueType) throws JsonMappingException
498+
{
499+
// (see comments from above method)
500+
JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType);
501+
if (ser == null) {
502+
ser = _serializerCache.untypedValueSerializer(valueType);
503+
if (ser == null) {
504+
ser = _serializerCache.untypedValueSerializer(_config.constructType(valueType));
505+
if (ser == null) {
506+
ser = _createAndCacheUntypedSerializer(valueType);
507+
if (ser == null) {
508+
ser = getUnknownTypeSerializer(valueType);
509+
if (CACHE_UNKNOWN_MAPPINGS) {
510+
_serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this);
511+
}
512+
}
513+
}
514+
}
515+
}
516+
return ser;
517+
}
518+
519+
/**
520+
* Method variant used when we do NOT want contextualization to happen; it will need
521+
* to be handled at a later point, but caller wants to be able to do that
522+
* as needed; sometimes to avoid infinite loops
523+
*
524+
* @since 2.5
525+
*/
526+
public JsonSerializer<Object> findValueSerializer(JavaType valueType)
527+
throws JsonMappingException
528+
{
529+
// (see comments from above method)
530+
JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType);
531+
if (ser == null) {
532+
ser = _serializerCache.untypedValueSerializer(valueType);
533+
if (ser == null) {
534+
ser = _createAndCacheUntypedSerializer(valueType);
535+
if (ser == null) {
536+
ser = getUnknownTypeSerializer(valueType.getRawClass());
537+
if (CACHE_UNKNOWN_MAPPINGS) {
538+
_serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this);
539+
}
540+
}
541+
}
542+
}
543+
return ser;
544+
}
545+
503546
/**
504547
* Similar to {@link #findValueSerializer(JavaType, BeanProperty)}, but used
505548
* when finding "primary" property value serializer (one directly handling

src/main/java/com/fasterxml/jackson/databind/ser/std/MapSerializer.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -188,14 +188,14 @@ public MapSerializer withResolved(BeanProperty property,
188188
}
189189
return ser;
190190
}
191-
191+
192192
/**
193193
* @since 2.3
194194
*/
195195
public MapSerializer withFilterId(Object filterId) {
196196
return (_filterId == filterId) ? this : new MapSerializer(this, filterId, _sortKeys);
197197
}
198-
198+
199199
/**
200200
* @since 2.3
201201
*/
@@ -375,7 +375,7 @@ public JsonSerializer<?> getKeySerializer() {
375375

376376
@Override
377377
public void serialize(Map<?,?> value, JsonGenerator jgen, SerializerProvider provider)
378-
throws IOException, JsonGenerationException
378+
throws IOException
379379
{
380380
jgen.writeStartObject();
381381
if (!value.isEmpty()) {
@@ -400,7 +400,7 @@ public void serialize(Map<?,?> value, JsonGenerator jgen, SerializerProvider pro
400400
@Override
401401
public void serializeWithType(Map<?,?> value, JsonGenerator jgen, SerializerProvider provider,
402402
TypeSerializer typeSer)
403-
throws IOException, JsonGenerationException
403+
throws IOException
404404
{
405405
typeSer.writeTypePrefixForObject(value, jgen);
406406
if (!value.isEmpty()) {
@@ -426,7 +426,7 @@ public void serializeWithType(Map<?,?> value, JsonGenerator jgen, SerializerProv
426426
* Method called to serialize fields, when the value type is not statically known.
427427
*/
428428
public void serializeFields(Map<?,?> value, JsonGenerator jgen, SerializerProvider provider)
429-
throws IOException, JsonGenerationException
429+
throws IOException
430430
{
431431
// If value type needs polymorphic type handling, some more work needed:
432432
if (_valueTypeSerializer != null) {
@@ -487,7 +487,7 @@ public void serializeFields(Map<?,?> value, JsonGenerator jgen, SerializerProvid
487487
*/
488488
protected void serializeFieldsUsing(Map<?,?> value, JsonGenerator jgen, SerializerProvider provider,
489489
JsonSerializer<Object> ser)
490-
throws IOException, JsonGenerationException
490+
throws IOException
491491
{
492492
final JsonSerializer<Object> keySerializer = _keySerializer;
493493
final HashSet<String> ignored = _ignoredEntries;
@@ -533,7 +533,7 @@ protected void serializeFieldsUsing(Map<?,?> value, JsonGenerator jgen, Serializ
533533
*/
534534
public void serializeFilteredFields(Map<?,?> value, JsonGenerator jgen, SerializerProvider provider,
535535
PropertyFilter filter)
536-
throws IOException, JsonGenerationException
536+
throws IOException
537537
{
538538
final HashSet<String> ignored = _ignoredEntries;
539539
final boolean skipNulls = !provider.isEnabled(SerializationFeature.WRITE_NULL_MAP_VALUES);
@@ -584,7 +584,7 @@ public void serializeFilteredFields(Map<?,?> value, JsonGenerator jgen, Serializ
584584
}
585585

586586
protected void serializeTypedFields(Map<?,?> value, JsonGenerator jgen, SerializerProvider provider)
587-
throws IOException, JsonGenerationException
587+
throws IOException
588588
{
589589
final JsonSerializer<Object> keySerializer = _keySerializer;
590590
JsonSerializer<Object> prevValueSerializer = null;

src/main/java/com/fasterxml/jackson/databind/ser/std/StdDelegatingSerializer.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,8 @@ public JsonSerializer<?> createContextual(SerializerProvider provider, BeanPrope
125125
}
126126
// and then find the thing...
127127
return withDelegate(_converter, delegateType,
128-
provider.findValueSerializer(delegateType, property));
128+
// provider.findValueSerializer(delegateType, property));
129+
provider.findValueSerializer(delegateType));
129130
}
130131

131132
/*

src/main/java/com/fasterxml/jackson/databind/ser/std/StdSerializer.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,14 +243,19 @@ protected JsonSerializer<?> findConvertingContentSerializer(SerializerProvider p
243243
BeanProperty prop, JsonSerializer<?> existingSerializer)
244244
throws JsonMappingException
245245
{
246+
/* 19-Oct-2014, tatu: As per [databind#357], need to avoid infinite loop
247+
* when applying contextual content converter; this is not ideal way,
248+
* but should work for most cases.
249+
*/
250+
246251
final AnnotationIntrospector intr = provider.getAnnotationIntrospector();
247252
if (intr != null && prop != null) {
248253
Object convDef = intr.findSerializationContentConverter(prop.getMember());
249254
if (convDef != null) {
250255
Converter<Object,Object> conv = provider.converterInstance(prop.getMember(), convDef);
251256
JavaType delegateType = conv.getOutputType(provider.getTypeFactory());
252257
if (existingSerializer == null) {
253-
existingSerializer = provider.findValueSerializer(delegateType, prop);
258+
existingSerializer = provider.findValueSerializer(delegateType);
254259
}
255260
return new StdDelegatingSerializer(conv, delegateType, existingSerializer);
256261
}

src/test/java/com/fasterxml/jackson/failing/TestConvertingSerializer357.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@ public class TestConvertingSerializer357
99
extends com.fasterxml.jackson.databind.BaseMapTest
1010
{
1111
// [Issue#357]
12-
static class A { }
12+
static class Value { }
1313

14-
static class B {
15-
@JsonSerialize(contentConverter = AToStringConverter.class)
16-
public List<A> list = Arrays.asList(new A());
14+
static class ListWrapper {
15+
@JsonSerialize(contentConverter = ValueToStringListConverter.class)
16+
public List<Value> list = Arrays.asList(new Value());
1717
}
1818

19-
static class AToStringConverter extends StdConverter<A, List<String>> {
19+
static class ValueToStringListConverter extends StdConverter<Value, List<String>> {
2020
@Override
21-
public List<String> convert(A value) {
21+
public List<String> convert(Value value) {
2222
return Arrays.asList("Hello world!");
2323
}
2424
}
@@ -31,7 +31,7 @@ public List<String> convert(A value) {
3131

3232
// [Issue#357]
3333
public void testConverterForList357() throws Exception {
34-
String json = objectWriter().writeValueAsString(new B());
34+
String json = objectWriter().writeValueAsString(new ListWrapper());
3535
assertEquals("{\"list\":[[\"Hello world!\"]]}", json);
3636
}
3737
}

0 commit comments

Comments
 (0)