Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Try to merge #4271 (for #1467) to master (2 failures wrt Creator name mismatch) #4797

Merged
merged 9 commits into from
Nov 14, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import tools.jackson.databind.cfg.*;
import tools.jackson.databind.deser.bean.CreatorCandidate;
import tools.jackson.databind.deser.bean.CreatorCollector;
import tools.jackson.databind.deser.impl.UnwrappedPropertyHandler;
import tools.jackson.databind.deser.jackson.JsonNodeDeserializer;
import tools.jackson.databind.deser.jackson.TokenBufferDeserializer;
import tools.jackson.databind.deser.jdk.*;
Expand Down Expand Up @@ -48,12 +49,6 @@ public abstract class BasicDeserializerFactory
private final static Class<?> CLASS_MAP_ENTRY = Map.Entry.class;
private final static Class<?> CLASS_SERIALIZABLE = Serializable.class;

/**
* We need a placeholder for creator properties that don't have name
* but are marked with `@JsonWrapped` annotation.
*/
protected final static PropertyName UNWRAPPED_CREATOR_PARAM_NAME = new PropertyName("@JsonUnwrapped");

/*
/**********************************************************************
/* Config
Expand Down Expand Up @@ -370,11 +365,8 @@ private void _addImplicitDelegatingConstructors(DeserializationContext ctxt,
}
NameTransformer unwrapper = intr.findUnwrappingNameTransformer(config, param);
if (unwrapper != null) {
_reportUnwrappedCreatorProperty(ctxt, beanDesc, param);
/*
properties[i] = constructCreatorProperty(ctxt, beanDesc, UNWRAPPED_CREATOR_PARAM_NAME, i, param, null);
++explicitNameCount;
*/
properties[i] = constructCreatorProperty(ctxt, beanDesc,
UnwrappedPropertyHandler.creatorParamName(i), i, param, null);
}
}

Expand Down Expand Up @@ -496,7 +488,8 @@ private void _addSelectedPropertiesBasedCreator(DeserializationContext ctxt,
// as that will not work with Creators well at all
NameTransformer unwrapper = intr.findUnwrappingNameTransformer(config, param);
if (unwrapper != null) {
_reportUnwrappedCreatorProperty(ctxt, beanDesc, param);
properties[i] = constructCreatorProperty(ctxt, beanDesc,
UnwrappedPropertyHandler.creatorParamName(i), i, param, null);
}
// Must be injectable or have name; without either won't work
if ((name == null) && (injectId == null)) {
Expand Down Expand Up @@ -563,16 +556,6 @@ private boolean _handleSingleArgumentCreator(CreatorCollector creators,
return false;
}

// 01-Dec-2016, tatu: As per [databind#265] we cannot yet support passing
// of unwrapped values through creator properties, so fail fast
private void _reportUnwrappedCreatorProperty(DeserializationContext ctxt,
BeanDescription beanDesc, AnnotatedParameter param)
{
ctxt.reportBadTypeDefinition(beanDesc,
"Cannot define Creator parameter %d as `@JsonUnwrapped`: combination not yet supported",
param.getIndex());
}

/**
* Method that will construct a property object that represents
* a logical property passed via Creator (constructor or static
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.lang.annotation.Annotation;

import tools.jackson.core.*;
import tools.jackson.core.util.InternCache;
import tools.jackson.databind.*;
import tools.jackson.databind.deser.bean.BeanDeserializer;
import tools.jackson.databind.deser.impl.FailingDeserializer;
Expand All @@ -12,6 +13,7 @@
import tools.jackson.databind.jsontype.TypeDeserializer;
import tools.jackson.databind.util.Annotations;
import tools.jackson.databind.util.ClassUtil;
import tools.jackson.databind.util.NameTransformer;
import tools.jackson.databind.util.ViewMatcher;

/**
Expand Down Expand Up @@ -577,6 +579,28 @@ public final Object deserializeWith(JsonParser p, DeserializationContext ctxt,
return value;
}

/**
* Returns a copy of this property, unwrapped using given {@link NameTransformer}.
*
* @since 2.19
*/
public SettableBeanProperty unwrapped(DeserializationContext ctxt, NameTransformer xf)
{
String newName = xf.transform(getName());
newName = InternCache.instance.intern(newName);
SettableBeanProperty renamed = withSimpleName(newName);
ValueDeserializer<?> deser = renamed.getValueDeserializer();
if (deser != null) {
@SuppressWarnings("unchecked")
ValueDeserializer<Object> newDeser = (ValueDeserializer<Object>)
deser.unwrappingDeserializer(ctxt, 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 @@ -1101,6 +1101,11 @@ protected Object deserializeUsingPropertyBasedWithUnwrapped(JsonParser p, Deseri
}
}

// We could still have some not-yet-set creator properties that are unwrapped.
// These have to be processed last, because 'tokens' contains all properties
// that remain after regular deserialization.
buffer = _unwrappedPropertyHandler.processUnwrappedCreatorProperties(p, ctxt, buffer, tokens);

// We hit END_OBJECT, so:
Object bean;
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ protected BeanDeserializerBase(BeanDeserializerBase src,

_unwrappedPropertyHandler = unwrapHandler;
_beanProperties = renamedProperties;

_needViewProcesing = src._needViewProcesing;
_serializationShape = src._serializationShape;

Expand Down Expand Up @@ -550,7 +551,13 @@ public void resolve(DeserializationContext ctxt)
if (unwrapped == null) {
unwrapped = new UnwrappedPropertyHandler();
}
unwrapped.addProperty(prop);

if (prop instanceof CreatorProperty) {
unwrapped.addCreatorProperty(prop);
} else {
unwrapped.addProperty(prop);
}

// 12-Dec-2014, tatu: As per [databind#647], we will have problems if
// the original property is left in place. So let's remove it now.
// 25-Mar-2017, tatu: Wonder if this could be problematic wrt creators?
Expand Down Expand Up @@ -973,13 +980,6 @@ protected NameTransformer _findPropertyUnwrapper(DeserializationContext ctxt,
NameTransformer unwrapper = ctxt.getAnnotationIntrospector().findUnwrappingNameTransformer(
ctxt.getConfig(), am);
if (unwrapper != null) {
// 01-Dec-2016, tatu: As per [databind#265] we cannot yet support passing
// of unwrapped values through creator properties, so fail fast
if (prop instanceof CreatorProperty) {
ctxt.reportBadDefinition(getValueType(), String.format(
"Cannot define Creator property \"%s\" as `@JsonUnwrapped`: combination not yet supported",
prop.getName()));
}
return unwrapper;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@

import tools.jackson.core.TokenStreamFactory;
import tools.jackson.core.sym.PropertyNameMatcher;
import tools.jackson.core.util.InternCache;
import tools.jackson.core.util.Named;
import tools.jackson.databind.DeserializationContext;
import tools.jackson.databind.PropertyName;
import tools.jackson.databind.ValueDeserializer;
import tools.jackson.databind.cfg.MapperConfig;
import tools.jackson.databind.deser.SettableBeanProperty;
import tools.jackson.databind.util.IgnorePropertiesUtil;
Expand Down Expand Up @@ -176,7 +174,7 @@ public BeanPropertyMap renameAll(DeserializationContext ctxt,
ArrayList<SettableBeanProperty> newProps = new ArrayList<SettableBeanProperty>(_propsInOrder.length);
for (int i = 0; i < len; ++i) {
SettableBeanProperty orig = _propsInOrder[i];
SettableBeanProperty prop = _rename(ctxt, orig, transformer);
SettableBeanProperty prop = orig.unwrapped(ctxt, transformer);
newProps.add(prop);
}
// 26-Feb-2017, tatu: Probably SHOULD handle renaming wrt Aliases?
Expand All @@ -187,26 +185,6 @@ public BeanPropertyMap renameAll(DeserializationContext ctxt,
.initMatcher(ctxt.tokenStreamFactory());
}

private SettableBeanProperty _rename(DeserializationContext ctxt,
SettableBeanProperty prop, NameTransformer xf)
{
if (prop != null) {
String newName = xf.transform(prop.getName());
newName = InternCache.instance.intern(newName);
prop = prop.withSimpleName(newName);
ValueDeserializer<?> deser = prop.getValueDeserializer();
if (deser != null) {
@SuppressWarnings("unchecked")
ValueDeserializer<Object> newDeser = (ValueDeserializer<Object>)
deser.unwrappingDeserializer(ctxt, xf);
if (newDeser != deser) {
prop = prop.withValueDeserializer(newDeser);
}
}
}
return prop;
}

/**
* Mutant factory method that will use this instance as the base, and
* construct an instance that is otherwise same except for excluding
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import tools.jackson.databind.deser.SettableBeanProperty;
import tools.jackson.databind.deser.ValueInstantiator;
import tools.jackson.databind.deser.impl.ObjectIdReader;
import tools.jackson.databind.util.NameTransformer;

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

/**
* @since 2.19
*/
protected PropertyBasedCreator(PropertyBasedCreator base,
HashMap<String, SettableBeanProperty> propertyLookup,
SettableBeanProperty[] allProperties)
{
_propertyCount = base._propertyCount;
_valueInstantiator = base._valueInstantiator;
_propertyLookup = propertyLookup;
_propertiesInOrder = allProperties;
}

/**
* Factory method used for building actual instances to be used with POJOS:
* resolves deserializers, checks for "null values".
Expand Down Expand Up @@ -143,6 +157,47 @@ public static PropertyBasedCreator construct(DeserializationContext ctxt,
caseInsensitive, false);
}

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

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

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

SettableBeanProperty renamedProperty = prop.unwrapped(ctxt, 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(this,
newLookup,
newProps.toArray(new SettableBeanProperty[0])
);
}

/*
/**********************************************************************
/* Accessors
Expand Down
Loading