diff options
author | Tatu Saloranta <tatu.saloranta@iki.fi> | 2020-06-16 23:07:44 -0700 |
---|---|---|
committer | Tatu Saloranta <tatu.saloranta@iki.fi> | 2020-06-16 23:07:44 -0700 |
commit | 87089aef0d62820c9ef496eb1f0a8f95263eba2b (patch) | |
tree | 343707995413eb7599e5f70dcc18b15bbaf6f529 /src | |
parent | d5e7bd16c6b78d1198f11b66c7814be12aad5c3f (diff) | |
download | jackson-databind-87089aef0d62820c9ef496eb1f0a8f95263eba2b.tar.gz |
Fixed #2759
Diffstat (limited to 'src')
-rw-r--r-- | src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializer.java | 14 | ||||
-rw-r--r-- | src/main/java/com/fasterxml/jackson/databind/ser/impl/BeanAsArraySerializer.java | 11 | ||||
-rw-r--r-- | src/main/java/com/fasterxml/jackson/databind/ser/impl/UnwrappingBeanSerializer.java | 14 | ||||
-rw-r--r-- | src/main/java/com/fasterxml/jackson/databind/ser/std/BeanSerializerBase.java | 56 | ||||
-rw-r--r-- | src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId2759Test.java (renamed from src/test/java/com/fasterxml/jackson/failing/JsonIdentityInfo2759Test.java) | 47 |
5 files changed, 101 insertions, 41 deletions
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializer.java index 94a4438d0..501f16d7f 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializer.java @@ -63,11 +63,17 @@ public class BeanSerializer ObjectIdWriter objectIdWriter, Object filterId) { super(src, objectIdWriter, filterId); } - + protected BeanSerializer(BeanSerializerBase src, Set<String> toIgnore) { super(src, toIgnore); } + // @since 2.11.1 + protected BeanSerializer(BeanSerializerBase src, + BeanPropertyWriter[] properties, BeanPropertyWriter[] filteredProperties) { + super(src, properties, filteredProperties); + } + /* /********************************************************** /* Life-cycle: factory methods, fluent factories @@ -114,6 +120,12 @@ public class BeanSerializer return new BeanSerializer(this, toIgnore); } + @Override // @since 2.11.1 + protected BeanSerializerBase withProperties(BeanPropertyWriter[] properties, + BeanPropertyWriter[] filteredProperties) { + return new BeanSerializer(this, properties, filteredProperties); + } + /** * Implementation has to check whether as-array serialization * is possible reliably; if (and only if) so, will construct diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/impl/BeanAsArraySerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/impl/BeanAsArraySerializer.java index 87d94b6a9..2abf7649d 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ser/impl/BeanAsArraySerializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/BeanAsArraySerializer.java @@ -6,6 +6,7 @@ import java.util.Set; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.core.type.WritableTypeId; + import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; @@ -111,12 +112,20 @@ public class BeanAsArraySerializer return new BeanAsArraySerializer(this, toIgnore); } + @Override // @since 2.11.1 + protected BeanSerializerBase withProperties(BeanPropertyWriter[] properties, + BeanPropertyWriter[] filteredProperties) { + // 16-Jun-2020, tatu: Added for [databind#2759] but with as-array we + // probably do not want to reorder anything; so actually leave unchanged + return this; + } + @Override protected BeanSerializerBase asArraySerializer() { // already is one, so: return this; } - + /* /********************************************************** /* JsonSerializer implementation that differs between impls diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnwrappingBeanSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnwrappingBeanSerializer.java index 3b91926a4..32418233f 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnwrappingBeanSerializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnwrappingBeanSerializer.java @@ -1,6 +1,7 @@ package com.fasterxml.jackson.databind.ser.impl; import com.fasterxml.jackson.core.JsonGenerator; + import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; @@ -54,6 +55,13 @@ public class UnwrappingBeanSerializer _nameTransformer = src._nameTransformer; } + // @since 2.11.1 + protected UnwrappingBeanSerializer(UnwrappingBeanSerializer src, + BeanPropertyWriter[] properties, BeanPropertyWriter[] filteredProperties) { + super(src, properties, filteredProperties); + _nameTransformer = src._nameTransformer; + } + /* /********************************************************** /* Life-cycle: factory methods, fluent factories @@ -86,6 +94,12 @@ public class UnwrappingBeanSerializer return new UnwrappingBeanSerializer(this, toIgnore); } + @Override // @since 2.11.1 + protected BeanSerializerBase withProperties(BeanPropertyWriter[] properties, + BeanPropertyWriter[] filteredProperties) { + return new UnwrappingBeanSerializer(this, properties, filteredProperties); + } + /** * JSON Array output cannot be done if unwrapping operation is * requested; so implementation will simply return 'this'. diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/BeanSerializerBase.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/BeanSerializerBase.java index f9f3f3ca3..271a93b9e 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ser/std/BeanSerializerBase.java +++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/BeanSerializerBase.java @@ -133,7 +133,7 @@ public abstract class BeanSerializerBase } } - public BeanSerializerBase(BeanSerializerBase src, + protected BeanSerializerBase(BeanSerializerBase src, BeanPropertyWriter[] properties, BeanPropertyWriter[] filteredProperties) { super(src._handledType); @@ -255,7 +255,16 @@ public abstract class BeanSerializerBase */ @Override public abstract BeanSerializerBase withFilterId(Object filterId); - + + /** + * Mutant factory used for creating a new instance with modified set + * of properties + * + * @since 2.11.1 + */ + protected abstract BeanSerializerBase withProperties(BeanPropertyWriter[] properties, + BeanPropertyWriter[] filteredProperties); + /** * Copy-constructor that is useful for sub-classes that just want to * copy all super-class properties without modifications. @@ -460,6 +469,10 @@ public abstract class BeanSerializerBase } ObjectIdWriter oiw = _objectIdWriter; + + // 16-Jun-2020, tatu: [databind#2759] means we need to handle reordering + // at a later point + int idPropOrigIndex = 0; Set<String> ignoredProps = null; Object newFilterId = null; @@ -484,7 +497,6 @@ public abstract class BeanSerializerBase // 2.1: allow modifications by "id ref" annotations as well: objectIdInfo = intr.findObjectReferenceInfo(accessor, objectIdInfo); - ObjectIdGenerator<?> gen; Class<?> implClass = objectIdInfo.getGeneratorType(); JavaType type = provider.constructType(implClass); JavaType idType = provider.getTypeFactory().findTypeParameters(type, ObjectIdGenerator.class)[0]; @@ -492,7 +504,7 @@ public abstract class BeanSerializerBase if (implClass == ObjectIdGenerators.PropertyGenerator.class) { // most special one, needs extra work String propName = objectIdInfo.getPropertyName().getSimpleName(); BeanPropertyWriter idProp = null; - + for (int i = 0, len = _props.length; ; ++i) { if (i == len) { provider.reportBadDefinition(_beanType, String.format( @@ -502,25 +514,17 @@ public abstract class BeanSerializerBase BeanPropertyWriter prop = _props[i]; if (propName.equals(prop.getName())) { idProp = prop; - // Let's force it to be the first property to output + // Let's mark id prop to be moved as the first (may still get rearranged) // (although it may still get rearranged etc) - if (i > 0) { // note: must shuffle both regular properties and filtered - System.arraycopy(_props, 0, _props, 1, i); - _props[0] = idProp; - if (_filteredProps != null) { - BeanPropertyWriter fp = _filteredProps[i]; - System.arraycopy(_filteredProps, 0, _filteredProps, 1, i); - _filteredProps[0] = fp; - } - } + idPropOrigIndex = i; break; } } idType = idProp.getType(); - gen = new PropertyBasedObjectIdGenerator(objectIdInfo, idProp); + ObjectIdGenerator<?> gen = new PropertyBasedObjectIdGenerator(objectIdInfo, idProp); oiw = ObjectIdWriter.construct(idType, (PropertyName) null, gen, objectIdInfo.getAlwaysAsId()); } else { // other types need to be simpler - gen = provider.objectIdGeneratorInstance(accessor, objectIdInfo); + ObjectIdGenerator<?> gen = provider.objectIdGeneratorInstance(accessor, objectIdInfo); oiw = ObjectIdWriter.construct(idType, objectIdInfo.getPropertyName(), gen, objectIdInfo.getAlwaysAsId()); } @@ -536,6 +540,25 @@ public abstract class BeanSerializerBase } // either way, need to resolve serializer: BeanSerializerBase contextual = this; + + // 16-Jun-2020, tatu: [databind#2759] must make copies, then reorder + if (idPropOrigIndex > 0) { // note: must shuffle both regular properties and filtered + final BeanPropertyWriter[] newProps = Arrays.copyOf(_props, _props.length); + BeanPropertyWriter bpw = newProps[idPropOrigIndex]; + System.arraycopy(newProps, 0, newProps, 1, idPropOrigIndex); + newProps[0] = bpw; + final BeanPropertyWriter[] newFiltered; + if (_filteredProps == null) { + newFiltered = null; + } else { + newFiltered = Arrays.copyOf(_filteredProps, _filteredProps.length); + bpw = newFiltered[idPropOrigIndex]; + System.arraycopy(newFiltered, 0, newFiltered, 1, idPropOrigIndex); + newFiltered[0] = bpw; + } + contextual = contextual.withProperties(newProps, newFiltered); + } + if (oiw != null) { JsonSerializer<?> ser = provider.findValueSerializer(oiw.idType, property); oiw = oiw.withSerializer(ser); @@ -550,6 +573,7 @@ public abstract class BeanSerializerBase if (newFilterId != null) { contextual = contextual.withFilterId(newFilterId); } + if (shape == null) { shape = _serializationShape; } diff --git a/src/test/java/com/fasterxml/jackson/failing/JsonIdentityInfo2759Test.java b/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId2759Test.java index d948b0c2a..9de0ec257 100644 --- a/src/test/java/com/fasterxml/jackson/failing/JsonIdentityInfo2759Test.java +++ b/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId2759Test.java @@ -1,21 +1,41 @@ -package com.fasterxml.jackson.failing; +package com.fasterxml.jackson.databind.objectid; import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.JsonIdentityReference; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.ObjectIdGenerators; import com.fasterxml.jackson.databind.*; -public class JsonIdentityInfo2759Test extends BaseMapTest +public class ObjectId2759Test extends BaseMapTest { + static class Hive { + public String name; + public List<Bee> bees = new ArrayList<>(); + + public Long id; + + Hive() { } + + public Hive(Long id, String name) { + this.id = id; + this.name = name; + } + + public void addBee(Bee bee) { + bees.add(bee); + } + } + static class Bee { public Long id; @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") -/// @JsonIdentityReference(alwaysAsId = true) -// @JsonProperty("hiveId") + @JsonIdentityReference(alwaysAsId = true) + @JsonProperty("hiveId") Hive hive; public Bee() { } @@ -34,24 +54,6 @@ public class JsonIdentityInfo2759Test extends BaseMapTest } } - static class Hive { - public String name; - public List<Bee> bees = new ArrayList<>(); - - public Long id; - - Hive() { } - - public Hive(Long id, String name) { - this.id = id; - this.name = name; - } - - public void addBee(Bee bee) { - bees.add(bee); - } - } - public void testObjectId2759() throws Exception { Hive hive = new Hive(100500L, "main hive"); @@ -60,7 +62,6 @@ public class JsonIdentityInfo2759Test extends BaseMapTest ObjectMapper mapper = newJsonMapper(); final String json = mapper.writerWithDefaultPrettyPrinter() .writeValueAsString(hive); - try { mapper.readerFor(JsonNode.class) .with(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY) |