Skip to content

Commit 1ed6b90

Browse files
authored
Merge branch '3.x' into tatu/3.0/4907-reduce-java-introspection
2 parents 939701f + 631b916 commit 1ed6b90

16 files changed

+135
-125
lines changed

release-notes/CREDITS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,8 @@ Yu Han (@hannyu)
5858
* Contributed #5158: Add "optional" variants -- shortValueOpt(), floatValueOpt(),
5959
asShortOpt(), asFloatOpt()
6060
[3.0.0]
61+
62+
Guillaume Smet (@gsmet)
63+
* Requested #4907: Reduce/eliminate introspection on `java.*` classes
64+
[3.0.0]
65+

release-notes/VERSION

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ Versions: 3.x (for earlier see VERSION-2.x)
77

88
3.0.0-rc5 (not yet released)
99

10+
#4907: Reduce/eliminate introspection on `java.*` classes
11+
(requested by Guillaume S)
1012
#5158: Add "optional" variants -- shortValueOpt(), floatValueOpt(), asShortOpt(),
1113
asFloatOpt()
1214
(contributed by Yu Han)

src/main/java/tools/jackson/databind/BeanDescription.java

Lines changed: 55 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.fasterxml.jackson.annotation.JsonFormat;
77
import com.fasterxml.jackson.annotation.JsonInclude;
88

9+
import tools.jackson.databind.cfg.MapperConfig;
910
import tools.jackson.databind.introspect.*;
1011
import tools.jackson.databind.util.Annotations;
1112

@@ -34,8 +35,8 @@ protected BeanDescription(JavaType type) {
3435
_type = type;
3536
}
3637

37-
public BeanDescription.Supplier supplier() {
38-
return new EagerSupplier(this);
38+
public BeanDescription.Supplier supplier(MapperConfig<?> config) {
39+
return new EagerSupplier(config, this);
3940
}
4041

4142
/*
@@ -226,12 +227,6 @@ public AnnotatedMember findJsonKeyAccessor() {
226227
*/
227228
public abstract JsonInclude.Value findPropertyInclusion(JsonInclude.Value defValue);
228229

229-
/**
230-
* Method for checking what is the expected format for POJO, as
231-
* defined by possible annotations and possible per-type config overrides.
232-
*/
233-
public abstract JsonFormat.Value findExpectedFormat(Class<?> baseType);
234-
235230
/*
236231
/**********************************************************************
237232
/* Basic API, other
@@ -280,21 +275,23 @@ public interface Supplier extends java.util.function.Supplier<BeanDescription>
280275
JavaType getType();
281276

282277
boolean isRecordType();
278+
279+
JsonFormat.Value findExpectedFormat(Class<?> baseType);
283280
}
284281

285-
/**
286-
* Partial implementation for lazily-constructed suppliers for {@link BeanDescription} instances.
287-
*/
288-
public static abstract class LazySupplier implements Supplier
282+
protected static abstract class SupplierBase implements Supplier
289283
{
284+
protected final MapperConfig<?> _config;
290285
protected final JavaType _type;
291286

292-
protected transient AnnotatedClass _classDesc;
287+
/**
288+
* Format definitions lazily introspected from class annotations
289+
*/
290+
protected transient JsonFormat.Value _classFormat;
293291

294-
protected transient BeanDescription _beanDesc;
295-
296-
protected LazySupplier(JavaType type) {
297-
_type = type;
292+
protected SupplierBase(MapperConfig<?> config, JavaType type) {
293+
_config = config;
294+
_type = type;
298295
}
299296

300297
// // Simple accessors:
@@ -308,6 +305,41 @@ protected LazySupplier(JavaType type) {
308305
@Override
309306
public boolean isRecordType() { return _type.isRecordType(); }
310307

308+
// // // Introspection
309+
310+
@Override
311+
public JsonFormat.Value findExpectedFormat(Class<?> baseType)
312+
{
313+
JsonFormat.Value v0 = _classFormat;
314+
if (v0 == null) { // copied from above
315+
v0 = _config.getAnnotationIntrospector().findFormat(_config,
316+
getClassInfo());
317+
if (v0 == null) {
318+
v0 = JsonFormat.Value.empty();
319+
}
320+
_classFormat = v0;
321+
}
322+
JsonFormat.Value v1 = _config.getDefaultPropertyFormat(baseType);
323+
if (v1 == null) {
324+
return v0;
325+
}
326+
return JsonFormat.Value.merge(v0, v1);
327+
}
328+
}
329+
330+
/**
331+
* Partial implementation for lazily-constructed suppliers for {@link BeanDescription} instances.
332+
*/
333+
public static abstract class LazySupplier extends SupplierBase
334+
{
335+
protected transient AnnotatedClass _classDesc;
336+
337+
protected transient BeanDescription _beanDesc;
338+
339+
protected LazySupplier(MapperConfig<?> config, JavaType type) {
340+
super(config, type);
341+
}
342+
311343
// // Entity accessors:
312344

313345
@Override
@@ -335,6 +367,8 @@ public BeanDescription get() {
335367
return _beanDesc;
336368
}
337369

370+
// // // Internal factory methods
371+
338372
protected abstract AnnotatedClass _introspect(JavaType forType);
339373

340374
protected abstract BeanDescription _construct(JavaType forType, AnnotatedClass ac);
@@ -344,23 +378,15 @@ public BeanDescription get() {
344378
* Simple {@link Supplier} implementation that just returns pre-constructed
345379
* {@link BeanDescription} instance.
346380
*/
347-
public static class EagerSupplier implements Supplier
381+
public static class EagerSupplier extends SupplierBase
348382
{
349383
protected final BeanDescription _beanDesc;
350384

351-
public EagerSupplier(BeanDescription beanDesc) {
352-
_beanDesc = Objects.requireNonNull(beanDesc);
385+
public EagerSupplier(MapperConfig<?> config, BeanDescription beanDesc) {
386+
super(config, beanDesc.getType());
387+
_beanDesc = beanDesc;
353388
}
354389

355-
@Override
356-
public Class<?> getBeanClass() { return _beanDesc.getBeanClass(); }
357-
358-
@Override
359-
public boolean isRecordType() { return getType().isRecordType(); }
360-
361-
@Override
362-
public JavaType getType() { return _beanDesc.getType(); }
363-
364390
@Override
365391
public BeanDescription get() { return _beanDesc; }
366392

src/main/java/tools/jackson/databind/DatabindContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ public abstract BeanDescription introspectBeanDescription(JavaType type,
319319
AnnotatedClass classDef);
320320

321321
public BeanDescription.Supplier lazyIntrospectBeanDescription(JavaType type) {
322-
return new BeanDescription.LazySupplier(type) {
322+
return new BeanDescription.LazySupplier(getConfig(), type) {
323323
@Override
324324
protected BeanDescription _construct(JavaType forType, AnnotatedClass ac) {
325325
System.out.println("lazyIntrospectBeanDescription.beanDesc("+forType+")");

src/main/java/tools/jackson/databind/DeserializationContext.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ public BeanDescription introspectBeanDescriptionForCreation(JavaType type, Annot
537537
}
538538

539539
public BeanDescription.Supplier lazyIntrospectBeanDescriptionForCreation(JavaType type) {
540-
return new BeanDescription.LazySupplier(type) {
540+
return new BeanDescription.LazySupplier(getConfig(), type) {
541541
@Override
542542
protected BeanDescription _construct(JavaType forType, AnnotatedClass ac) {
543543
return introspectBeanDescriptionForCreation(forType, ac);
@@ -558,7 +558,7 @@ public BeanDescription introspectBeanDescriptionForBuilder(JavaType builderType,
558558

559559
public BeanDescription.Supplier lazyIntrospectBeanDescriptionForBuilder(final JavaType builderType,
560560
final BeanDescription valueTypeDesc) {
561-
return new BeanDescription.LazySupplier(builderType) {
561+
return new BeanDescription.LazySupplier(getConfig(), builderType) {
562562
@Override
563563
protected BeanDescription _construct(JavaType forType, AnnotatedClass ac) {
564564
return introspectBeanDescriptionForBuilder(forType, valueTypeDesc);

src/main/java/tools/jackson/databind/JsonNode.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -756,10 +756,10 @@ public String asText(String defaultValue) {
756756

757757
/**
758758
* Method similar to {@link #shortValue()}, but that will return empty
759-
* {@link Optional<Short>} ({@code Optional.empty()}) if this node cannot
759+
* {@code Optional<Short>} ({@code Optional.empty()}) if this node cannot
760760
* be converted to Java {@code short}.
761761
*
762-
* @return Java {@code short} value this node represents, as {@link Optional<Short>},
762+
* @return Java {@code short} value this node represents, as {@code Optional<Short>},
763763
* if possible to accurately represent; {@code Optional.empty()} otherwise
764764
*/
765765
public abstract Optional<Short> shortValueOpt();
@@ -803,7 +803,7 @@ public String asText(String defaultValue) {
803803
* ({@code Optional.empty()}) if this node cannot
804804
* be coerced to {@code short}.
805805
*
806-
* @return {@link Optional<Short>} value this node represents,
806+
* @return {@code Optional<Short>} value this node represents,
807807
* if possible to accurately represent; {@code Optional.empty()} otherwise
808808
*/
809809
public abstract Optional<Short> asShortOpt();
@@ -1104,10 +1104,10 @@ public String asText(String defaultValue) {
11041104

11051105
/**
11061106
* Method similar to {@link #floatValue()}, but that will return empty
1107-
* {@link Optional<Float>} ({@code Optional.empty()}) if this node cannot
1107+
* {@code Optional<Float>} ({@code Optional.empty()}) if this node cannot
11081108
* be converted to Java {@code float}.
11091109
*
1110-
* @return Java {@code float} value this node represents, as {@link Optional<Float>},
1110+
* @return Java {@code float} value this node represents, as {@code Optional<Float>},
11111111
* if possible to accurately represent; {@code Optional.empty()} otherwise
11121112
*/
11131113
public abstract Optional<Float> floatValueOpt();
@@ -1145,7 +1145,7 @@ public String asText(String defaultValue) {
11451145
* ({@code Optional.empty()}) if this node cannot
11461146
* be coerced to {@code float}.
11471147
*
1148-
* @return {@link Optional<Float>} value this node represents,
1148+
* @return {@code Optional<Float>} value this node represents,
11491149
* if possible to accurately represent; {@code Optional.empty()} otherwise
11501150
*/
11511151
public abstract Optional<Float> asFloatOpt();

src/main/java/tools/jackson/databind/deser/BeanDeserializerBuilder.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,8 @@ public class BeanDeserializerBuilder
127127
/**********************************************************************
128128
*/
129129

130-
public BeanDeserializerBuilder(BeanDescription.Supplier beanDescRef,
131-
DeserializationContext ctxt)
130+
public BeanDeserializerBuilder(DeserializationContext ctxt,
131+
BeanDescription.Supplier beanDescRef)
132132
{
133133
_beanDescRef = beanDescRef;
134134
_context = ctxt;
@@ -584,7 +584,7 @@ protected BeanPropertyMap _constructPropMap(Collection<SettableBeanProperty> pro
584584
{
585585
// 07-May-2020, tatu: First find combination of per-type config overrides (higher
586586
// precedence) and per-type annotations (lower):
587-
JsonFormat.Value format = _beanDescRef.get().findExpectedFormat(null);
587+
JsonFormat.Value format = _beanDescRef.findExpectedFormat(null);
588588
// and see if any of those has explicit definition; if not, use global baseline default
589589
Boolean B = format.getFeature(JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES);
590590
boolean caseInsensitive = (B == null)

src/main/java/tools/jackson/databind/deser/BeanDeserializerFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ public ValueDeserializer<Object> buildThrowableDeserializer(DeserializationConte
492492
*/
493493
protected BeanDeserializerBuilder constructBeanDeserializerBuilder(DeserializationContext ctxt,
494494
BeanDescription.Supplier beanDescRef) {
495-
return new BeanDeserializerBuilder(beanDescRef, ctxt);
495+
return new BeanDeserializerBuilder(ctxt, beanDescRef);
496496
}
497497

498498
/**

src/main/java/tools/jackson/databind/deser/DeserializerCache.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -378,11 +378,11 @@ protected ValueDeserializer<?> _createDeserializer2(DeserializationContext ctxt,
378378
}
379379
if (type.isMapLikeType()) {
380380
// 11-Mar-2017, tatu: As per [databind#1554], also need to block
381-
// handling as Map if overriden with "as POJO" option.
381+
// handling as Map if overridden with "as POJO" option.
382382
// Ideally we'd determine it bit later on (to allow custom handler checks)
383383
// but that won't work for other reasons. So do it here.
384384
// (read: rewrite for 3.0)
385-
JsonFormat.Value format = beanDescRef.get().findExpectedFormat(type.getRawClass());
385+
JsonFormat.Value format = beanDescRef.findExpectedFormat(type.getRawClass());
386386
if (format.getShape() != JsonFormat.Shape.POJO) {
387387
MapLikeType mlt = (MapLikeType) type;
388388
if (mlt instanceof MapType) {
@@ -392,11 +392,10 @@ protected ValueDeserializer<?> _createDeserializer2(DeserializationContext ctxt,
392392
}
393393
}
394394
if (type.isCollectionLikeType()) {
395-
/* One exception is if shape is to be Shape.POJO (or, as alias, OBJECT).
396-
* Ideally we'd determine it bit later on (to allow custom handler checks),
397-
* but that won't work for other reasons. So do it here.
398-
*/
399-
JsonFormat.Value format = beanDescRef.get().findExpectedFormat(type.getRawClass());
395+
// One exception is if shape is to be Shape.POJO (or, as alias, OBJECT).
396+
// Ideally we'd determine it bit later on (to allow custom handler checks),
397+
// but that won't work for other reasons. So do it here.
398+
JsonFormat.Value format = beanDescRef.findExpectedFormat(type.getRawClass());
400399
if (format.getShape() != JsonFormat.Shape.POJO) {
401400
CollectionLikeType clt = (CollectionLikeType) type;
402401
if (clt instanceof CollectionType) {

src/main/java/tools/jackson/databind/deser/bean/BeanDeserializerBase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ protected BeanDeserializerBase(BeanDeserializerBuilder builder,
247247
;
248248

249249
// Any transformation we may need to apply?
250-
_serializationShape = beanDescRef.get().findExpectedFormat(_beanType.getRawClass()).getShape();
250+
_serializationShape = beanDescRef.findExpectedFormat(_beanType.getRawClass()).getShape();
251251

252252
_needViewProcesing = hasViews;
253253
_vanillaProcessing = !_nonStandardCreation

src/main/java/tools/jackson/databind/introspect/BasicBeanDescription.java

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -371,28 +371,6 @@ public AnnotatedMethod findMethod(String name, Class<?>[] paramTypes) {
371371
/**********************************************************************
372372
*/
373373

374-
@Override
375-
public JsonFormat.Value findExpectedFormat(Class<?> baseType)
376-
{
377-
JsonFormat.Value v0 = _classFormat;
378-
if (v0 == null) { // copied from above
379-
// 18-Apr-2018, tatu: Bit unclean but apparently `_config` is `null` for
380-
// a small set of pre-discovered simple types that `BasicClassIntrospector`
381-
// may expose. If so, nothing we can do
382-
v0 = (_config == null) ? null
383-
: _intr.findFormat(_config, _classInfo);
384-
if (v0 == null) {
385-
v0 = JsonFormat.Value.empty();
386-
}
387-
_classFormat = v0;
388-
}
389-
JsonFormat.Value v1 = _config.getDefaultPropertyFormat(baseType);
390-
if (v1 == null) {
391-
return v0;
392-
}
393-
return JsonFormat.Value.merge(v0, v1);
394-
}
395-
396374
@Override
397375
public Class<?>[] findDefaultViews()
398376
{

0 commit comments

Comments
 (0)