diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index bfd62f87df..387f919e20 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -14,6 +14,9 @@ Project: jackson-databind (fix contributed by Migwel@github) #3038: Two cases of incorrect error reporting about DeserializationFeature (reported by Jelle V) +#3045: Bug in polymorphic deserialization with `@JsonCreator`, `@JsonAnySetter`, + `JsonTypeInfo.As.EXTERNAL_PROPERTY` + (reported by martineaus83@github) #3055: Polymorphic subtype deduction ignores `defaultImpl` attribute (contributed by drekbour@github) #3056: MismatchedInputException: Cannot deserialize instance of diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java index d9311914f1..3716d93989 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java @@ -947,9 +947,15 @@ protected Object deserializeWithExternalTypeId(JsonParser p, DeserializationCont Object bean) throws IOException { - final Class activeView = _needViewProcesing ? ctxt.getActiveView() : null; - final ExternalTypeHandler ext = _externalTypeIdHandler.start(); + return _deserializeWithExternalTypeId(p, ctxt, bean, + _externalTypeIdHandler.start()); + } + protected Object _deserializeWithExternalTypeId(JsonParser p, DeserializationContext ctxt, + Object bean, ExternalTypeHandler ext) + throws IOException + { + final Class activeView = _needViewProcesing ? ctxt.getActiveView() : null; for (JsonToken t = p.currentToken(); t == JsonToken.FIELD_NAME; t = p.nextToken()) { String propName = p.currentName(); t = p.nextToken(); @@ -996,15 +1002,14 @@ protected Object deserializeWithExternalTypeId(JsonParser p, DeserializationCont } @SuppressWarnings("resource") - protected Object deserializeUsingPropertyBasedWithExternalTypeId(JsonParser p, DeserializationContext ctxt) + protected Object deserializeUsingPropertyBasedWithExternalTypeId(JsonParser p, + DeserializationContext ctxt) throws IOException { final ExternalTypeHandler ext = _externalTypeIdHandler.start(); final PropertyBasedCreator creator = _propertyBasedCreator; PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader); - - TokenBuffer tokens = new TokenBuffer(p, ctxt); - tokens.writeStartObject(); + final Class activeView = _needViewProcesing ? ctxt.getActiveView() : null; JsonToken t = p.currentToken(); for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) { @@ -1024,7 +1029,8 @@ protected Object deserializeUsingPropertyBasedWithExternalTypeId(JsonParser p, D ; } else { // Last creator property to set? - if (buffer.assignParameter(creatorProp, _deserializeWithErrorWrapping(p, ctxt, creatorProp))) { + if (buffer.assignParameter(creatorProp, + _deserializeWithErrorWrapping(p, ctxt, creatorProp))) { t = p.nextToken(); // to move to following FIELD_NAME/END_OBJECT Object bean; try { @@ -1033,12 +1039,6 @@ protected Object deserializeUsingPropertyBasedWithExternalTypeId(JsonParser p, D wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt); continue; // never gets here } - // if so, need to copy all remaining tokens into buffer - while (t == JsonToken.FIELD_NAME) { - p.nextToken(); // to skip name - tokens.copyCurrentStructure(p); - t = p.nextToken(); - } if (bean.getClass() != _beanType.getRawClass()) { // !!! 08-Jul-2011, tatu: Could theoretically support; but for now // it's too complicated, so bail out @@ -1046,7 +1046,7 @@ protected Object deserializeUsingPropertyBasedWithExternalTypeId(JsonParser p, D "Cannot create polymorphic instances with external type ids (%s -> %s)", _beanType, bean.getClass())); } - return ext.complete(p, ctxt, bean); + return _deserializeWithExternalTypeId(p, ctxt, bean, ext); } } continue; @@ -1058,7 +1058,12 @@ protected Object deserializeUsingPropertyBasedWithExternalTypeId(JsonParser p, D if (t.isScalarValue()) { ext.handleTypePropertyValue(p, ctxt, propName, null); } - buffer.bufferProperty(prop, prop.deserialize(p, ctxt)); + // 19-Feb-2021, tatu: Should probably consider view too? + if (activeView != null && !prop.visibleInView(activeView)) { + p.skipChildren(); + } else { + buffer.bufferProperty(prop, prop.deserialize(p, ctxt)); + } continue; } // external type id (or property that depends on it)? @@ -1079,7 +1084,6 @@ protected Object deserializeUsingPropertyBasedWithExternalTypeId(JsonParser p, D // Unknown: let's call handler method handleUnknownProperty(p, ctxt, _valueClass, propName); } - tokens.writeEndObject(); // We hit END_OBJECT; resolve the pieces: try { diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeIdWithCreator3045Test.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeIdWithCreator3045Test.java index 036215193c..821f863133 100644 --- a/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeIdWithCreator3045Test.java +++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeIdWithCreator3045Test.java @@ -95,17 +95,19 @@ public String toString() { public void testExternalIdWithAnySetter3045() throws Exception { + // First cases where the last Creator argument comes last: _testExternalIdWithAnySetter3045(a2q( "{'type':'track','data':{'data-internal':'toto'},'time':345}")); _testExternalIdWithAnySetter3045(a2q( "{'data':{'data-internal':'toto'},'type':'track', 'time':345}")); - /* + // then a case where it comes in the middle _testExternalIdWithAnySetter3045(a2q( "{'data':{'data-internal':'toto'},'time':345, 'type':'track'}")); + + // and finally one where we'll start with it _testExternalIdWithAnySetter3045(a2q( "{'time':345, 'type':'track', 'data':{'data-internal':'toto'}}")); - */ } private void _testExternalIdWithAnySetter3045(String input) throws Exception