Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Expand Up @@ -373,6 +373,10 @@ public DeserializationConfig withRootName(PropertyName rootName) {
return new DeserializationConfig(this, rootName);
}

public DeserializationConfig withRadix(int radix) {
return _withBase(_base.withRadix(radix));
}

@Override
public DeserializationConfig withView(Class<?> view) {
return (_view == view) ? this : new DeserializationConfig(this, view);
Expand Down
14 changes: 13 additions & 1 deletion src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@ public boolean useForType(JavaType t)
// 16-May-2009, tatu: Ditto ^^^
protected final static AnnotationIntrospector DEFAULT_ANNOTATION_INTROSPECTOR = new JacksonAnnotationIntrospector();

protected static final int DEFAULT_RADIX = 10;
/**
* Base settings contain defaults used for all {@link ObjectMapper}
* instances.
Expand All @@ -419,7 +420,7 @@ public boolean useForType(JavaType t)
// Since 2.12:
new DefaultAccessorNamingStrategy.Provider(),
// Since 2.16: [databind#2502] Add a way to configure Caches Jackson uses
DefaultCacheProvider.defaultInstance()
DefaultCacheProvider.defaultInstance(), DEFAULT_RADIX
);

/*
Expand Down Expand Up @@ -2545,6 +2546,17 @@ public ObjectMapper setDateFormat(DateFormat dateFormat)
return this;
}

/**
* Method for configuring the radix to use when serializing integral types
* as strings.
*/
public ObjectMapper setRadix(int radix)
{
_deserializationConfig = _deserializationConfig.withRadix(radix);
_serializationConfig = _serializationConfig.withRadix(radix);
return this;
}

/**
* @since 2.5
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,10 @@ public SerializationConfig with(SubtypeResolver str) {
return (str == _subtypeResolver)? this : new SerializationConfig(this, str);
}

public SerializationConfig withRadix(int radix) {
return _withBase(_base.withRadix(radix));
}

@Override
public SerializationConfig withView(Class<?> view) {
return (_view == view) ? this : new SerializationConfig(this, view);
Expand Down
89 changes: 58 additions & 31 deletions src/main/java/com/fasterxml/jackson/databind/cfg/BaseSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,11 @@ public final class BaseSettings
*/
protected final CacheProvider _cacheProvider;

/**
* Default radix to use when serializing/deserializing integers to string.
*/
protected final int _defaultRadix;

/*
/**********************************************************
/* Construction
Expand All @@ -165,11 +170,11 @@ public final class BaseSettings
* @since 2.19
*/
public BaseSettings(ClassIntrospector ci, AnnotationIntrospector ai,
PropertyNamingStrategy pns, EnumNamingStrategy ens, TypeFactory tf,
TypeResolverBuilder<?> typer, DateFormat dateFormat, HandlerInstantiator hi,
Locale locale, TimeZone tz, Base64Variant defaultBase64,
PolymorphicTypeValidator ptv, AccessorNamingStrategy.Provider accNaming,
CacheProvider cacheProvider)
PropertyNamingStrategy pns, EnumNamingStrategy ens, TypeFactory tf,
TypeResolverBuilder<?> typer, DateFormat dateFormat, HandlerInstantiator hi,
Locale locale, TimeZone tz, Base64Variant defaultBase64,
PolymorphicTypeValidator ptv, AccessorNamingStrategy.Provider accNaming,
CacheProvider cacheProvider, int defaultRadix)
{
_classIntrospector = ci;
_annotationIntrospector = ai;
Expand All @@ -185,6 +190,7 @@ public BaseSettings(ClassIntrospector ci, AnnotationIntrospector ai,
_typeValidator = ptv;
_accessorNaming = accNaming;
_cacheProvider = cacheProvider;
_defaultRadix = defaultRadix;
}

/**
Expand All @@ -193,13 +199,13 @@ public BaseSettings(ClassIntrospector ci, AnnotationIntrospector ai,
*/
@Deprecated
public BaseSettings(ClassIntrospector ci, AnnotationIntrospector ai,
PropertyNamingStrategy pns, TypeFactory tf,
TypeResolverBuilder<?> typer, DateFormat dateFormat, HandlerInstantiator hi,
Locale locale, TimeZone tz, Base64Variant defaultBase64,
PolymorphicTypeValidator ptv, AccessorNamingStrategy.Provider accNaming,
CacheProvider cacheProvider)
PropertyNamingStrategy pns, TypeFactory tf,
TypeResolverBuilder<?> typer, DateFormat dateFormat, HandlerInstantiator hi,
Locale locale, TimeZone tz, Base64Variant defaultBase64,
PolymorphicTypeValidator ptv, AccessorNamingStrategy.Provider accNaming,
CacheProvider cacheProvider, int defaultRadix)
{
this(ci, ai, pns, null, tf, typer, dateFormat, hi, locale, tz, defaultBase64, ptv, accNaming, cacheProvider);
this(ci, ai, pns, null, tf, typer, dateFormat, hi, locale, tz, defaultBase64, ptv, accNaming, cacheProvider, defaultRadix);
}

/**
Expand All @@ -208,13 +214,13 @@ public BaseSettings(ClassIntrospector ci, AnnotationIntrospector ai,
*/
@Deprecated
public BaseSettings(ClassIntrospector ci, AnnotationIntrospector ai,
PropertyNamingStrategy pns, TypeFactory tf,
TypeResolverBuilder<?> typer, DateFormat dateFormat, HandlerInstantiator hi,
Locale locale, TimeZone tz, Base64Variant defaultBase64,
PolymorphicTypeValidator ptv, AccessorNamingStrategy.Provider accNaming)
PropertyNamingStrategy pns, TypeFactory tf,
TypeResolverBuilder<?> typer, DateFormat dateFormat, HandlerInstantiator hi,
Locale locale, TimeZone tz, Base64Variant defaultBase64,
PolymorphicTypeValidator ptv, AccessorNamingStrategy.Provider accNaming, int defaultRadix)
{
this(ci, ai, pns, tf, typer, dateFormat, hi, locale, tz, defaultBase64, ptv, accNaming,
DefaultCacheProvider.defaultInstance());
DefaultCacheProvider.defaultInstance(), defaultRadix);
}

/**
Expand All @@ -237,7 +243,8 @@ public BaseSettings copy() {
_defaultBase64,
_typeValidator,
_accessorNaming,
_cacheProvider);
_cacheProvider,
_defaultRadix);
}

/*
Expand All @@ -252,7 +259,7 @@ public BaseSettings withClassIntrospector(ClassIntrospector ci) {
}
return new BaseSettings(ci, _annotationIntrospector, _propertyNamingStrategy, _enumNamingStrategy,
_typeFactory, _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale,
_timeZone, _defaultBase64, _typeValidator, _accessorNaming, _cacheProvider);
_timeZone, _defaultBase64, _typeValidator, _accessorNaming, _cacheProvider, _defaultRadix);
}

public BaseSettings withAnnotationIntrospector(AnnotationIntrospector ai) {
Expand All @@ -261,7 +268,7 @@ public BaseSettings withAnnotationIntrospector(AnnotationIntrospector ai) {
}
return new BaseSettings(_classIntrospector, ai, _propertyNamingStrategy, _enumNamingStrategy,
_typeFactory, _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale,
_timeZone, _defaultBase64, _typeValidator, _accessorNaming, _cacheProvider);
_timeZone, _defaultBase64, _typeValidator, _accessorNaming, _cacheProvider, _defaultRadix);
}

public BaseSettings withInsertedAnnotationIntrospector(AnnotationIntrospector ai) {
Expand All @@ -288,7 +295,7 @@ public BaseSettings withPropertyNamingStrategy(PropertyNamingStrategy pns) {
}
return new BaseSettings(_classIntrospector, _annotationIntrospector, pns, _enumNamingStrategy,
_typeFactory, _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale,
_timeZone, _defaultBase64, _typeValidator, _accessorNaming, _cacheProvider);
_timeZone, _defaultBase64, _typeValidator, _accessorNaming, _cacheProvider, _defaultRadix);
}

/**
Expand All @@ -300,7 +307,7 @@ public BaseSettings withEnumNamingStrategy(EnumNamingStrategy ens) {
}
return new BaseSettings(_classIntrospector, _annotationIntrospector, _propertyNamingStrategy, ens,
_typeFactory, _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale,
_timeZone, _defaultBase64, _typeValidator, _accessorNaming, _cacheProvider);
_timeZone, _defaultBase64, _typeValidator, _accessorNaming, _cacheProvider, _defaultRadix);
}

// @since 2.12
Expand All @@ -310,7 +317,7 @@ public BaseSettings withAccessorNaming(AccessorNamingStrategy.Provider p) {
}
return new BaseSettings(_classIntrospector, _annotationIntrospector, _propertyNamingStrategy, _enumNamingStrategy,
_typeFactory, _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale,
_timeZone, _defaultBase64, _typeValidator, p, _cacheProvider);
_timeZone, _defaultBase64, _typeValidator, p, _cacheProvider, _defaultRadix);
}

public BaseSettings withTypeFactory(TypeFactory tf) {
Expand All @@ -319,7 +326,7 @@ public BaseSettings withTypeFactory(TypeFactory tf) {
}
return new BaseSettings(_classIntrospector, _annotationIntrospector, _propertyNamingStrategy, _enumNamingStrategy,
tf, _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale,
_timeZone, _defaultBase64, _typeValidator, _accessorNaming, _cacheProvider);
_timeZone, _defaultBase64, _typeValidator, _accessorNaming, _cacheProvider, _defaultRadix);
}

public BaseSettings withTypeResolverBuilder(TypeResolverBuilder<?> typer) {
Expand All @@ -328,7 +335,7 @@ public BaseSettings withTypeResolverBuilder(TypeResolverBuilder<?> typer) {
}
return new BaseSettings(_classIntrospector, _annotationIntrospector, _propertyNamingStrategy, _enumNamingStrategy,
_typeFactory, typer, _dateFormat, _handlerInstantiator, _locale,
_timeZone, _defaultBase64, _typeValidator, _accessorNaming, _cacheProvider);
_timeZone, _defaultBase64, _typeValidator, _accessorNaming, _cacheProvider, _defaultRadix);
}

public BaseSettings withDateFormat(DateFormat df) {
Expand All @@ -342,7 +349,7 @@ public BaseSettings withDateFormat(DateFormat df) {
}
return new BaseSettings(_classIntrospector, _annotationIntrospector, _propertyNamingStrategy, _enumNamingStrategy,
_typeFactory, _typeResolverBuilder, df, _handlerInstantiator, _locale,
_timeZone, _defaultBase64, _typeValidator, _accessorNaming, _cacheProvider);
_timeZone, _defaultBase64, _typeValidator, _accessorNaming, _cacheProvider, _defaultRadix);
}

public BaseSettings withHandlerInstantiator(HandlerInstantiator hi) {
Expand All @@ -351,7 +358,7 @@ public BaseSettings withHandlerInstantiator(HandlerInstantiator hi) {
}
return new BaseSettings(_classIntrospector, _annotationIntrospector, _propertyNamingStrategy, _enumNamingStrategy,
_typeFactory, _typeResolverBuilder, _dateFormat, hi, _locale,
_timeZone, _defaultBase64, _typeValidator, _accessorNaming, _cacheProvider);
_timeZone, _defaultBase64, _typeValidator, _accessorNaming, _cacheProvider, _defaultRadix);
}

public BaseSettings with(Locale l) {
Expand All @@ -360,7 +367,7 @@ public BaseSettings with(Locale l) {
}
return new BaseSettings(_classIntrospector, _annotationIntrospector, _propertyNamingStrategy, _enumNamingStrategy,
_typeFactory,_typeResolverBuilder, _dateFormat, _handlerInstantiator, l,
_timeZone, _defaultBase64, _typeValidator, _accessorNaming, _cacheProvider);
_timeZone, _defaultBase64, _typeValidator, _accessorNaming, _cacheProvider, _defaultRadix);
}

/**
Expand All @@ -383,7 +390,7 @@ public BaseSettings with(TimeZone tz)
return new BaseSettings(_classIntrospector, _annotationIntrospector,
_propertyNamingStrategy, _enumNamingStrategy, _typeFactory,
_typeResolverBuilder, df, _handlerInstantiator, _locale,
tz, _defaultBase64, _typeValidator, _accessorNaming, _cacheProvider);
tz, _defaultBase64, _typeValidator, _accessorNaming, _cacheProvider, _defaultRadix);
}

/**
Expand All @@ -396,7 +403,7 @@ public BaseSettings with(Base64Variant base64) {
return new BaseSettings(_classIntrospector, _annotationIntrospector,
_propertyNamingStrategy, _enumNamingStrategy, _typeFactory,
_typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale,
_timeZone, base64, _typeValidator, _accessorNaming, _cacheProvider);
_timeZone, base64, _typeValidator, _accessorNaming, _cacheProvider, _defaultRadix);
}

/**
Expand All @@ -409,7 +416,7 @@ public BaseSettings with(PolymorphicTypeValidator v) {
return new BaseSettings(_classIntrospector, _annotationIntrospector,
_propertyNamingStrategy, _enumNamingStrategy, _typeFactory,
_typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale,
_timeZone, _defaultBase64, v, _accessorNaming, _cacheProvider);
_timeZone, _defaultBase64, v, _accessorNaming, _cacheProvider, _defaultRadix);
}

/**
Expand All @@ -425,7 +432,23 @@ public BaseSettings with(CacheProvider cacheProvider) {
return new BaseSettings(_classIntrospector, _annotationIntrospector,
_propertyNamingStrategy, _enumNamingStrategy, _typeFactory,
_typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale,
_timeZone, _defaultBase64, _typeValidator, _accessorNaming, cacheProvider);
_timeZone, _defaultBase64, _typeValidator, _accessorNaming, cacheProvider, _defaultRadix);
}

/**
* Fluent factory for constructing a new instance with provided default radix.
*
* @return a new instance with provided defaultRadix.
* @since 2.21
*/
public BaseSettings withRadix(int defaultRadix) {
if (defaultRadix == _defaultRadix) {
return this;
}
return new BaseSettings(_classIntrospector, _annotationIntrospector,
_propertyNamingStrategy, _enumNamingStrategy, _typeFactory,
_typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale,
_timeZone, _defaultBase64, _typeValidator, _accessorNaming, _cacheProvider, defaultRadix);
}

/*
Expand Down Expand Up @@ -503,6 +526,10 @@ public boolean hasExplicitTimeZone() {
public Base64Variant getBase64Variant() {
return _defaultBase64;
}

public int getRadix() {
return _defaultRadix;
}

/**
* @since 2.16
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,14 @@ public Base64Variant getBase64Variant() {
return _base.getBase64Variant();
}

/**
* Method called during deserialization if a Number needs to be decoded from
* String. Default version just returns radix 10.
*/
public int getRadix() {
return _base.getRadix();
}

/**
* Method for accessing per-instance shared (baseline/default)
* attribute values; these are used as the basis for per-call
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,12 @@ public T withRootName(String rootName) {
*/
public abstract T with(SubtypeResolver str);

/**
* Method for constructing and returning a new instance with different
* radix to use.
*/
public abstract T withRadix(int radix);

/**
* Method for constructing and returning a new instance with different
* view to use.
Expand Down Expand Up @@ -933,8 +939,8 @@ public PropertyName findRootName(Class<?> rawRootType) {
public final Class<?> findMixInClassFor(Class<?> cls) {
return _mixIns.findMixInClassFor(cls);
}

// Not really relevant here (should not get called)

@Override
public MixInResolver copy() {
throw new UnsupportedOperationException();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.fasterxml.jackson.databind.deser.std;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;

import java.io.IOException;
import java.math.BigInteger;

/**
* Deserializer used to deserialize string that represent number under in specific radix (base).
*/
public class FromStringWithRadixToNumberDeserializer
extends StdDeserializer<Number> {
private final int radix;

public FromStringWithRadixToNumberDeserializer(StdDeserializer<?> src, int radix) {
super(src);
this.radix = radix;
}

@Override
public Number deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException {
Class<?> handledType = handledType();

if (p.currentToken() != JsonToken.VALUE_STRING) {
ctxt.reportInputMismatch(handledType,
"Read something other than string when deserializing a value using FromStringWithRadixToNumberDeserializer.");
}

String text = p.getText();

if (handledType.equals(BigInteger.class)) {
return new BigInteger(text, radix);
} else if (handledType.equals(byte.class) || handledType.equals(Byte.class)) {
return Byte.parseByte(text, radix);
} else if (handledType.equals(short.class) || handledType.equals(Short.class)) {
return Short.parseShort(text, radix);
} else if (handledType.equals(int.class) || handledType.equals(Integer.class)) {
return Integer.parseInt(text, radix);
} else if (handledType.equals(long.class) || handledType.equals(Long.class)) {
return Long.parseLong(text, radix);
} else {
ctxt.reportInputMismatch(handledType,
"Trying to deserialize a non-whole number with NumberToStringWithRadixSerializer");
Copy link
Author

@tiger9800 tiger9800 Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I considered explicitly throwing here, but this seemed like a more common way to indicate an error.

return null;//should not reach here
}
}
}
Loading