Skip to content

Fixed #2215 - Support BigInteger and BigDecimal in StdValueInstantiator #2793

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

Merged
merged 1 commit into from
Jul 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.fasterxml.jackson.databind.deser;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicReference;
Expand Down Expand Up @@ -948,6 +950,16 @@ protected boolean _handleSingleArgumentCreator(CreatorCollector creators,
}
return true;
}
if (type == BigInteger.class) {
if (isCreator || isVisible) {
creators.addBigIntegerCreator(ctor, isCreator);
}
}
if (type == BigDecimal.class) {
if (isCreator || isVisible) {
creators.addBigDecimalCreator(ctor, isCreator);
}
}
// Delegating Creator ok iff it has @JsonCreator (etc)
if (isCreator) {
creators.addDelegatingCreator(ctor, isCreator, null, 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1390,15 +1390,19 @@ public Object deserializeFromNumber(JsonParser p, DeserializationContext ctxt)
}
return _valueInstantiator.createFromLong(ctxt, p.getLongValue());
}
// actually, could also be BigInteger, so:
if (delegateDeser != null) {
Object bean = _valueInstantiator.createUsingDelegate(ctxt,
delegateDeser.deserialize(p, ctxt));
if (_injectables != null) {
injectValues(ctxt, bean);
if (nt == NumberType.BIG_INTEGER) {
if (delegateDeser != null) {
if (!_valueInstantiator.canCreateFromBigInteger()) {
Object bean = _valueInstantiator.createUsingDelegate(ctxt, delegateDeser.deserialize(p, ctxt));
if (_injectables != null) {
injectValues(ctxt, bean);
}
return bean;
}
}
return bean;
return _valueInstantiator.createFromBigInteger(ctxt, p.getBigIntegerValue());
}

return ctxt.handleMissingInstantiator(handledType(), getValueInstantiator(), p,
"no suitable creator method found to deserialize from Number value (%s)",
p.getNumberValue());
Expand Down Expand Up @@ -1449,12 +1453,22 @@ public Object deserializeFromDouble(JsonParser p, DeserializationContext ctxt) t
}
return _valueInstantiator.createFromDouble(ctxt, p.getDoubleValue());
}
// actually, could also be BigDecimal, so:
JsonDeserializer<Object> delegateDeser = _delegateDeserializer();
if (delegateDeser != null) {
return _valueInstantiator.createUsingDelegate(ctxt,
delegateDeser.deserialize(p, ctxt));

if (t == NumberType.BIG_DECIMAL) {
JsonDeserializer<Object> delegateDeser = _delegateDeserializer();
if (delegateDeser != null) {
if (!_valueInstantiator.canCreateFromBigDecimal()) {
Object bean = _valueInstantiator.createUsingDelegate(ctxt, delegateDeser.deserialize(p, ctxt));
if (_injectables != null) {
injectValues(ctxt, bean);
}
return bean;
}
}

return _valueInstantiator.createFromBigDecimal(ctxt, p.getDecimalValue());
}

return ctxt.handleMissingInstantiator(handledType(), getValueInstantiator(), p,
"no suitable creator method found to deserialize from Number value (%s)",
p.getNumberValue());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import com.fasterxml.jackson.databind.deser.impl.PropertyValueBuffer;
import com.fasterxml.jackson.databind.introspect.AnnotatedWithParams;
import com.fasterxml.jackson.databind.type.LogicalType;
import java.math.BigDecimal;
import java.math.BigInteger;

/**
* Class that defines simple API implemented by objects that create value
Expand Down Expand Up @@ -137,18 +139,31 @@ public boolean canInstantiate() {
*/
public boolean canCreateFromLong() { return false; }

/**
* Method that can be called to check whether a BigInteger based creator is available
* to use (to call {@link #createFromBigInteger}). +
*/
public boolean canCreateFromBigInteger() { return false; }

/**
* Method that can be called to check whether a double (double / Double) based
* creator is available to use (to call {@link #createFromDouble}).
*/
public boolean canCreateFromDouble() { return false; }

/**
* Method that can be called to check whether a BigDecimal based creator is available
* to use (to call {@link #createFromBigDecimal}).
*/
public boolean canCreateFromBigDecimal() { return false; }

/**
* Method that can be called to check whether a double (boolean / Boolean) based
* creator is available to use (to call {@link #createFromDouble}).
*/
public boolean canCreateFromBoolean() { return false; }


/**
* Method that can be called to check whether a default creator (constructor,
* or no-arg static factory method)
Expand Down Expand Up @@ -263,7 +278,7 @@ public Object createFromObjectWith(DeserializationContext ctxt, Object[] args) t
* {@link PropertyValueBuffer#getParameter(SettableBeanProperty)} to safely
* read the present properties only, and to have some other behavior for the
* missing properties.
*
*
* @since 2.8
*/
public Object createFromObjectWith(DeserializationContext ctxt,
Expand Down Expand Up @@ -316,12 +331,28 @@ public Object createFromLong(DeserializationContext ctxt, long value) throws IOE
value);
}

public Object createFromBigInteger(DeserializationContext ctxt, BigInteger value) throws IOException
{
return ctxt.handleMissingInstantiator(getValueClass(),this,null,
"no BigInteger-argument constructor/factory method to deserialize from Number value (%s)",
value
);
}

public Object createFromDouble(DeserializationContext ctxt, double value) throws IOException {
return ctxt.handleMissingInstantiator(getValueClass(), this, null,
"no double/Double-argument constructor/factory method to deserialize from Number value (%s)",
value);
}

public Object createFromBigDecimal(DeserializationContext ctxt, BigDecimal value) throws IOException
{
return ctxt.handleMissingInstantiator(getValueClass(),this,null,
"no BigDecimal/double/Double-argument constructor/factory method to deserialize from Number value (%s)",
value
);
}

public Object createFromBoolean(DeserializationContext ctxt, boolean value) throws IOException {
return ctxt.handleMissingInstantiator(getValueClass(), this, null,
"no boolean/Boolean-argument constructor/factory method to deserialize from boolean value (%s)",
Expand Down Expand Up @@ -444,7 +475,7 @@ public Base(Class<?> type) {
public Base(JavaType type) {
_valueType = type.getRawClass();
}

@Override
public String getValueTypeDesc() {
return _valueType.getName();
Expand All @@ -468,7 +499,7 @@ public static class Delegating extends ValueInstantiator
private static final long serialVersionUID = 1L;

protected final ValueInstantiator _delegate;

protected Delegating(ValueInstantiator delegate) {
_delegate = delegate;
}
Expand Down Expand Up @@ -574,11 +605,21 @@ public Object createFromLong(DeserializationContext ctxt, long value) throws IOE
return delegate().createFromLong(ctxt, value);
}

@Override
public Object createFromBigInteger(DeserializationContext ctxt, BigInteger value) throws IOException {
return delegate().createFromBigInteger(ctxt, value);
}

@Override
public Object createFromDouble(DeserializationContext ctxt, double value) throws IOException {
return delegate().createFromDouble(ctxt, value);
}

@Override
public Object createFromBigDecimal(DeserializationContext ctxt, BigDecimal value) throws IOException {
return delegate().createFromBigDecimal(ctxt, value);
}

@Override
public Object createFromBoolean(DeserializationContext ctxt, boolean value) throws IOException {
return delegate().createFromBoolean(ctxt, value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,17 @@ public class CreatorCollector {
protected final static int C_STRING = 1;
protected final static int C_INT = 2;
protected final static int C_LONG = 3;
protected final static int C_DOUBLE = 4;
protected final static int C_BOOLEAN = 5;
protected final static int C_DELEGATE = 6;
protected final static int C_PROPS = 7;
protected final static int C_ARRAY_DELEGATE = 8;
protected final static int C_BIG_INTEGER = 4;
protected final static int C_DOUBLE = 5;
protected final static int C_BIG_DECIMAL = 6;
protected final static int C_BOOLEAN = 7;
protected final static int C_DELEGATE = 8;
protected final static int C_PROPS = 9;
protected final static int C_ARRAY_DELEGATE = 10;

protected final static String[] TYPE_DESCS = new String[] { "default",
"from-String", "from-int", "from-long", "from-double",
"from-boolean", "delegate", "property-based", "array-delegate"
"from-String", "from-int", "from-long", "from-big-integer", "from-double",
"from-big-decimal", "from-boolean", "delegate", "property-based", "array-delegate"
};

// Type of bean being created
Expand All @@ -47,7 +49,7 @@ public class CreatorCollector {
*
* @since 2.5
*/
final protected AnnotatedWithParams[] _creators = new AnnotatedWithParams[9];
final protected AnnotatedWithParams[] _creators = new AnnotatedWithParams[11];

/**
* Bitmask of creators that were explicitly marked as creators; false for
Expand Down Expand Up @@ -99,7 +101,9 @@ public ValueInstantiator constructValueInstantiator(DeserializationContext ctxt)
inst.configureFromStringCreator(_creators[C_STRING]);
inst.configureFromIntCreator(_creators[C_INT]);
inst.configureFromLongCreator(_creators[C_LONG]);
inst.configureFromBigIntegerCreator(_creators[C_BIG_INTEGER]);
inst.configureFromDoubleCreator(_creators[C_DOUBLE]);
inst.configureFromBigDecimalCreator(_creators[C_BIG_DECIMAL]);
inst.configureFromBooleanCreator(_creators[C_BOOLEAN]);
return inst;
}
Expand Down Expand Up @@ -136,10 +140,18 @@ public void addLongCreator(AnnotatedWithParams creator, boolean explicit) {
verifyNonDup(creator, C_LONG, explicit);
}

public void addBigIntegerCreator(AnnotatedWithParams creator, boolean explicit) {
verifyNonDup(creator, C_BIG_INTEGER, explicit);
}

public void addDoubleCreator(AnnotatedWithParams creator, boolean explicit) {
verifyNonDup(creator, C_DOUBLE, explicit);
}

public void addBigDecimalCreator(AnnotatedWithParams creator, boolean explicit) {
verifyNonDup(creator, C_BIG_DECIMAL, explicit);
}

public void addBooleanCreator(AnnotatedWithParams creator, boolean explicit) {
verifyNonDup(creator, C_BOOLEAN, explicit);
}
Expand Down
Loading