From d338aa5049600d29c0784f5b9cda06ad1cc7626b Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Tue, 29 Nov 2016 20:18:36 -0800 Subject: [PATCH] Fixed #349 --- release-notes/VERSION | 2 + .../databind/deser/BeanDeserializer.java | 71 +++++++++++++++---- .../deser/impl/UnwrappedPropertyHandler.java | 12 ++-- .../deser}/AnySetter349Test.java | 10 +-- 4 files changed, 69 insertions(+), 26 deletions(-) rename src/test/java/com/fasterxml/jackson/{failing => databind/deser}/AnySetter349Test.java (82%) diff --git a/release-notes/VERSION b/release-notes/VERSION index 8ed7af41cc..2ebf37bf45 100644 --- a/release-notes/VERSION +++ b/release-notes/VERSION @@ -6,6 +6,8 @@ Project: jackson-databind 2.8.6 (not yet released) +#349: @JsonAnySetter with @JsonUnwrapped: deserialization fails with arrays + (reported by hdave@github) #1388: `@JsonIdentityInfo`: id has to be the first key in deserialization when deserializing with `@JsonCreator` (reported by moodysalem@github) 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 1960d5733e..4090163e46 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java @@ -632,13 +632,24 @@ protected Object deserializeWithUnwrapped(JsonParser p, DeserializationContext c handleIgnoredProperty(p, ctxt, bean, propName); continue; } - // but... others should be passed to unwrapped property deserializers - tokens.writeFieldName(propName); - tokens.copyCurrentStructure(p); + // 29-Nov-2016, tatu: probably should try to avoid sending content + // both to any setter AND buffer... but, for now, the only thing + // we can do. // how about any setter? We'll get copies but... - if (_anySetter != null) { + if (_anySetter == null) { + // but... others should be passed to unwrapped property deserializers + tokens.writeFieldName(propName); + tokens.copyCurrentStructure(p); + } else { + // Need to copy to a separate buffer first + TokenBuffer b2 = new TokenBuffer(p, ctxt); + b2.copyCurrentStructure(p); + tokens.writeFieldName(propName); + tokens.append(b2); try { - _anySetter.deserializeAndSet(p, ctxt, bean, propName); + JsonParser p2 = b2.asParser(p); + p2.nextToken(); + _anySetter.deserializeAndSet(p2, ctxt, bean, propName); } catch (Exception e) { wrapAndThrow(e, bean, propName, ctxt); } @@ -681,12 +692,28 @@ protected Object deserializeWithUnwrapped(JsonParser p, DeserializationContext c handleIgnoredProperty(p, ctxt, bean, propName); continue; } - // but... others should be passed to unwrapped property deserializers - tokens.writeFieldName(propName); - tokens.copyCurrentStructure(p); + // 29-Nov-2016, tatu: probably should try to avoid sending content + // both to any setter AND buffer... but, for now, the only thing + // we can do. // how about any setter? We'll get copies but... - if (_anySetter != null) { - _anySetter.deserializeAndSet(p, ctxt, bean, propName); + if (_anySetter == null) { + // but... others should be passed to unwrapped property deserializers + tokens.writeFieldName(propName); + tokens.copyCurrentStructure(p); + } else { + // Need to copy to a separate buffer first + TokenBuffer b2 = new TokenBuffer(p, ctxt); + b2.copyCurrentStructure(p); + tokens.writeFieldName(propName); + tokens.append(b2); + try { + JsonParser p2 = b2.asParser(p); + p2.nextToken(); + _anySetter.deserializeAndSet(p2, ctxt, bean, propName); + } catch (Exception e) { + wrapAndThrow(e, bean, propName, ctxt); + } + continue; } } tokens.writeEndObject(); @@ -755,15 +782,29 @@ protected Object deserializeUsingPropertyBasedWithUnwrapped(JsonParser p, Deseri handleIgnoredProperty(p, ctxt, handledType(), propName); continue; } - tokens.writeFieldName(propName); - tokens.copyCurrentStructure(p); - // "any property"? - if (_anySetter != null) { + // 29-Nov-2016, tatu: probably should try to avoid sending content + // both to any setter AND buffer... but, for now, the only thing + // we can do. + // how about any setter? We'll get copies but... + if (_anySetter == null) { + // but... others should be passed to unwrapped property deserializers + tokens.writeFieldName(propName); + tokens.copyCurrentStructure(p); + } else { + // Need to copy to a separate buffer first + TokenBuffer b2 = new TokenBuffer(p, ctxt); + b2.copyCurrentStructure(p); + tokens.writeFieldName(propName); + tokens.append(b2); try { - buffer.bufferAnyProperty(_anySetter, propName, _anySetter.deserialize(p, ctxt)); + JsonParser p2 = b2.asParser(p); + p2.nextToken(); + buffer.bufferAnyProperty(_anySetter, propName, + _anySetter.deserialize(p2, ctxt)); } catch (Exception e) { wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt); } + continue; } } diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/UnwrappedPropertyHandler.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/UnwrappedPropertyHandler.java index 181c52a2f4..890ff7b91a 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/UnwrappedPropertyHandler.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/UnwrappedPropertyHandler.java @@ -51,15 +51,15 @@ public UnwrappedPropertyHandler renameAll(NameTransformer transformer) } @SuppressWarnings("resource") - public Object processUnwrapped(JsonParser originalParser, DeserializationContext ctxt, Object bean, - TokenBuffer buffered) - throws IOException, JsonProcessingException + public Object processUnwrapped(JsonParser originalParser, DeserializationContext ctxt, + Object bean, TokenBuffer buffered) + throws IOException { for (int i = 0, len = _properties.size(); i < len; ++i) { SettableBeanProperty prop = _properties.get(i); - JsonParser jp = buffered.asParser(); - jp.nextToken(); - prop.deserializeAndSet(jp, ctxt, bean); + JsonParser p = buffered.asParser(); + p.nextToken(); + prop.deserializeAndSet(p, ctxt, bean); } return bean; } diff --git a/src/test/java/com/fasterxml/jackson/failing/AnySetter349Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/AnySetter349Test.java similarity index 82% rename from src/test/java/com/fasterxml/jackson/failing/AnySetter349Test.java rename to src/test/java/com/fasterxml/jackson/databind/deser/AnySetter349Test.java index c4f0d56812..5ff1d2b371 100644 --- a/src/test/java/com/fasterxml/jackson/failing/AnySetter349Test.java +++ b/src/test/java/com/fasterxml/jackson/databind/deser/AnySetter349Test.java @@ -1,4 +1,4 @@ -package com.fasterxml.jackson.failing; +package com.fasterxml.jackson.databind.deser; import java.util.*; @@ -26,7 +26,7 @@ public Map getProperties() { } @JsonUnwrapped - public IdentityDTO349 identity = null; + public IdentityDTO349 identity; } static class IdentityDTO349 { @@ -38,9 +38,9 @@ public void testUnwrappedWithAny() throws Exception final ObjectMapper mapper = objectMapper(); final String json = aposToQuotes( "{ 'type' : 'IST',\n" -+" 'spacename' : 'Foo Models',\n" -+" 'name' : 'BLAH-New',\n" -+" 'description' : 'namespace.name: X THIN FIR.DR-WD12-New',\n" +//+" 'spacename' : 'Foo Models',\n" +//+" 'name' : 'BLAH-New',\n" +//+" 'description' : 'namespace.name: X THIN FIR.DR-WD12-New',\n" +" 'ZoomLinks': [ 'foofoofoofoo', 'barbarbarbar' ] }" ); Bean349 value = mapper.readValue(json, Bean349.class);