Skip to content

Commit

Permalink
fix @JsonUnwrapped for fields with property based creator
Browse files Browse the repository at this point in the history
  • Loading branch information
fxshlein committed Jan 6, 2024
1 parent 7ef8358 commit d65dfac
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,6 @@ protected BeanDeserializerBase(BeanDeserializerBase src, NameTransformer unwrapp
_valueInstantiator = src._valueInstantiator;
_delegateDeserializer = src._delegateDeserializer;
_arrayDelegateDeserializer = src._arrayDelegateDeserializer;
_propertyBasedCreator = src._propertyBasedCreator;

_backRefs = src._backRefs;
_ignorableProps = src._ignorableProps;
Expand All @@ -318,15 +317,18 @@ protected BeanDeserializerBase(BeanDeserializerBase src, NameTransformer unwrapp

_nonStandardCreation = src._nonStandardCreation;
UnwrappedPropertyHandler uph = src._unwrappedPropertyHandler;
PropertyBasedCreator pbc = src._propertyBasedCreator;

if (unwrapper != null) {
// delegate further unwraps, if any
if (uph != null) { // got handler, delegate
uph = uph.renameAll(unwrapper);
}
// and handle direct unwrapping as well:
_propertyBasedCreator = pbc != null ? pbc.renameAll(unwrapper) : null;
_beanProperties = src._beanProperties.renameAll(unwrapper);
} else {
_propertyBasedCreator = pbc;
_beanProperties = src._beanProperties;
}
_unwrappedPropertyHandler = uph;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
import com.fasterxml.jackson.databind.util.Annotations;
import com.fasterxml.jackson.databind.util.ClassUtil;
import com.fasterxml.jackson.databind.util.NameTransformer;
import com.fasterxml.jackson.databind.util.ViewMatcher;

/**
Expand Down Expand Up @@ -586,6 +587,25 @@ public final Object deserializeWith(JsonParser p, DeserializationContext ctxt,
return value;
}

/**
* Returns a copy of this property, unwrapped using the given {@link NameTransformer}.
*/
public SettableBeanProperty unwrapped(NameTransformer xf)
{
String newName = xf.transform(getName());
SettableBeanProperty renamed = withSimpleName(newName);
JsonDeserializer<?> deser = renamed.getValueDeserializer();
if (deser != null) {
@SuppressWarnings("unchecked")
JsonDeserializer<Object> newDeser = (JsonDeserializer<Object>)
deser.unwrappingDeserializer(xf);
if (newDeser != deser) {
renamed = renamed.withValueDeserializer(newDeser);
}
}
return renamed;
}

/*
/**********************************************************
/* Helper methods
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.PropertyName;
Expand Down Expand Up @@ -362,7 +361,7 @@ public BeanPropertyMap renameAll(NameTransformer transformer)
newProps.add(prop);
continue;
}
newProps.add(_rename(prop, transformer));
newProps.add(prop.unwrapped(transformer));
}
// should we try to re-index? Ordering probably changed but caller probably doesn't want changes...
// 26-Feb-2017, tatu: Probably SHOULD handle renaming wrt Aliases?
Expand Down Expand Up @@ -713,25 +712,6 @@ public String toString()
/**********************************************************
*/

protected SettableBeanProperty _rename(SettableBeanProperty prop, NameTransformer xf)
{
if (prop == null) {
return prop;
}
String newName = xf.transform(prop.getName());
prop = prop.withSimpleName(newName);
JsonDeserializer<?> deser = prop.getValueDeserializer();
if (deser != null) {
@SuppressWarnings("unchecked")
JsonDeserializer<Object> newDeser = (JsonDeserializer<Object>)
deser.unwrappingDeserializer(xf);
if (newDeser != deser) {
prop = prop.withValueDeserializer(newDeser);
}
}
return prop;
}

protected void wrapAndThrow(Throwable t, Object bean, String fieldName, DeserializationContext ctxt)
throws IOException
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
import com.fasterxml.jackson.databind.deser.ValueInstantiator;
import com.fasterxml.jackson.databind.util.NameTransformer;

/**
* Object that is used to collect arguments for non-default creator
Expand Down Expand Up @@ -92,6 +93,18 @@ protected PropertyBasedCreator(DeserializationContext ctxt,
}
}

protected PropertyBasedCreator(
int propertyCount,
ValueInstantiator valueInstantiator,
HashMap<String, SettableBeanProperty> propertyLookup,
SettableBeanProperty[] allProperties
) {
this._propertyCount = propertyCount;
this._valueInstantiator = valueInstantiator;
this._propertyLookup = propertyLookup;
this._allProperties = allProperties;
}

/**
* Factory method used for building actual instances to be used with POJOS:
* resolves deserializers, checks for "null values".
Expand Down Expand Up @@ -158,6 +171,46 @@ public static PropertyBasedCreator construct(DeserializationContext ctxt,
ctxt.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES));
}

/**
* Mutant factory method for constructing a map where the names of all properties
* are transformed using the given {@link NameTransformer}.
*/
public PropertyBasedCreator renameAll(NameTransformer transformer)
{
if (transformer == null || (transformer == NameTransformer.NOP)) {
return this;
}

final int len = _allProperties.length;
HashMap<String, SettableBeanProperty> newLookup = new HashMap<>(_propertyLookup);
ArrayList<SettableBeanProperty> newProps = new ArrayList<>(len);

for (SettableBeanProperty prop : _allProperties) {
if (prop == null) {
newProps.add(null);
continue;
}

SettableBeanProperty renamedProperty = prop.unwrapped(transformer);
String oldName = prop.getName();
String newName = renamedProperty.getName();

newProps.add(renamedProperty);

if (!oldName.equals(newName) && newLookup.containsKey(oldName)) {
newLookup.remove(oldName);
newLookup.put(newName, renamedProperty);
}
}

return new PropertyBasedCreator(
_propertyCount,
_valueInstantiator,
newLookup,
newProps.toArray(new SettableBeanProperty[newProps.size()])
);
}

/*
/**********************************************************
/* Accessors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.PropertyName;
import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
import com.fasterxml.jackson.databind.util.NameTransformer;
Expand Down Expand Up @@ -59,17 +56,12 @@ private List<SettableBeanProperty> renameProperties(
) {
List<SettableBeanProperty> newProps = new ArrayList<>(properties.size());
for (SettableBeanProperty prop : properties) {
String newName = transformer.transform(prop.getName());
prop = prop.withSimpleName(newName);
JsonDeserializer<?> deser = prop.getValueDeserializer();
if (deser != null) {
@SuppressWarnings("unchecked")
JsonDeserializer<Object> newDeser = (JsonDeserializer<Object>) deser.unwrappingDeserializer(transformer);
if (newDeser != deser) {
prop = prop.withValueDeserializer(newDeser);
}
if (prop == null) {
newProps.add(null);
continue;
}
newProps.add(prop);

newProps.add(prop.unwrapped(transformer));
}
return newProps;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.fasterxml.jackson.databind.struct;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import com.fasterxml.jackson.databind.BaseMapTest;
import com.fasterxml.jackson.databind.ObjectMapper;

public class UnwrappedPropertyBasedCreatorWithPrefixTest extends BaseMapTest
{
static class Outer {
@JsonUnwrapped(prefix = "inner-")
Inner inner;
}

static class Inner {
private final String _property;

public Inner(@JsonProperty("property") String property) {
_property = property;
}

public String getProperty() {
return _property;
}
}

/*
/**********************************************************
/* Tests, deserialization
/**********************************************************
*/

private final ObjectMapper MAPPER = newJsonMapper();

public void testUnwrappedWithJsonCreatorWithExplicitWithoutName() throws Exception
{
String json = "{\"inner-property\": \"value\"}";
Outer outer = MAPPER.readValue(json, Outer.class);

assertEquals("value", outer.inner.getProperty());
}
}

0 comments on commit d65dfac

Please sign in to comment.