aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTatu Saloranta <tatu.saloranta@iki.fi>2020-06-16 23:07:44 -0700
committerTatu Saloranta <tatu.saloranta@iki.fi>2020-06-16 23:07:44 -0700
commit87089aef0d62820c9ef496eb1f0a8f95263eba2b (patch)
tree343707995413eb7599e5f70dcc18b15bbaf6f529 /src
parentd5e7bd16c6b78d1198f11b66c7814be12aad5c3f (diff)
downloadjackson-databind-87089aef0d62820c9ef496eb1f0a8f95263eba2b.tar.gz
Fixed #2759
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializer.java14
-rw-r--r--src/main/java/com/fasterxml/jackson/databind/ser/impl/BeanAsArraySerializer.java11
-rw-r--r--src/main/java/com/fasterxml/jackson/databind/ser/impl/UnwrappingBeanSerializer.java14
-rw-r--r--src/main/java/com/fasterxml/jackson/databind/ser/std/BeanSerializerBase.java56
-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)