3232import com .fasterxml .jackson .annotation .JsonInclude .Include ;
3333import com .fasterxml .jackson .annotation .PropertyAccessor ;
3434import org .jspecify .annotations .Nullable ;
35+ import tools .jackson .core .StreamReadConstraints ;
36+ import tools .jackson .core .StreamWriteConstraints ;
37+ import tools .jackson .core .base .DecorableTSFactory .DecorableTSFBuilder ;
38+ import tools .jackson .core .json .JsonFactory ;
39+ import tools .jackson .core .json .JsonFactoryBuilder ;
3540import tools .jackson .databind .JacksonModule ;
3641import tools .jackson .databind .ObjectMapper ;
3742import tools .jackson .databind .PropertyNamingStrategies ;
4045import tools .jackson .databind .cfg .DateTimeFeature ;
4146import tools .jackson .databind .cfg .MapperBuilder ;
4247import tools .jackson .databind .json .JsonMapper ;
48+ import tools .jackson .dataformat .cbor .CBORFactory ;
49+ import tools .jackson .dataformat .cbor .CBORFactoryBuilder ;
4350import tools .jackson .dataformat .cbor .CBORMapper ;
51+ import tools .jackson .dataformat .xml .XmlFactory ;
52+ import tools .jackson .dataformat .xml .XmlFactoryBuilder ;
4453import tools .jackson .dataformat .xml .XmlMapper ;
4554
4655import org .springframework .aot .hint .ReflectionHints ;
5564import org .springframework .boot .autoconfigure .condition .ConditionalOnClass ;
5665import org .springframework .boot .autoconfigure .condition .ConditionalOnMissingBean ;
5766import org .springframework .boot .context .properties .EnableConfigurationProperties ;
67+ import org .springframework .boot .context .properties .PropertyMapper ;
5868import org .springframework .boot .jackson .JacksonComponentModule ;
5969import org .springframework .boot .jackson .JacksonMixinModule ;
6070import org .springframework .boot .jackson .JacksonMixinModuleEntries ;
6171import org .springframework .boot .jackson .autoconfigure .JacksonProperties .ConstructorDetectorStrategy ;
72+ import org .springframework .boot .jackson .autoconfigure .JacksonProperties .Factory .Constraints ;
73+ import org .springframework .boot .jackson .autoconfigure .JacksonProperties .Factory .Constraints .Read ;
74+ import org .springframework .boot .jackson .autoconfigure .JacksonProperties .Factory .Constraints .Write ;
6275import org .springframework .context .ApplicationContext ;
6376import org .springframework .context .annotation .Bean ;
6477import org .springframework .context .annotation .Configuration ;
@@ -94,11 +107,21 @@ JacksonComponentModule jsonComponentModule() {
94107 return new JacksonComponentModule ();
95108 }
96109
110+ @ Bean
111+ @ ConditionalOnMissingBean
112+ JsonFactory jsonFactory (List <JsonFactoryBuilderCustomizer > customizers ) {
113+ JsonFactoryBuilder builder = JsonFactory .builder ();
114+ for (JsonFactoryBuilderCustomizer customizer : customizers ) {
115+ customizer .customize (builder );
116+ }
117+ return builder .build ();
118+ }
119+
97120 @ Bean
98121 @ Scope (ConfigurableBeanFactory .SCOPE_PROTOTYPE )
99122 @ ConditionalOnMissingBean
100- JsonMapper .Builder jsonMapperBuilder (List <JsonMapperBuilderCustomizer > customizers ) {
101- JsonMapper .Builder builder = JsonMapper .builder ();
123+ JsonMapper .Builder jsonMapperBuilder (List <JsonMapperBuilderCustomizer > customizers , JsonFactory jsonFactory ) {
124+ JsonMapper .Builder builder = JsonMapper .builder (jsonFactory );
102125 customize (builder , customizers );
103126 return builder ;
104127 }
@@ -137,12 +160,36 @@ JacksonMixinModule jacksonMixinModule(ApplicationContext context, JacksonMixinMo
137160
138161 @ Configuration (proxyBeanMethods = false )
139162 @ EnableConfigurationProperties (JacksonProperties .class )
140- static class JacksonJsonMapperBuilderCustomizerConfiguration {
163+ static class JacksonJsonCustomizerConfiguration {
164+
165+ private final JacksonProperties jacksonProperties ;
166+
167+ JacksonJsonCustomizerConfiguration (JacksonProperties jacksonProperties ) {
168+ this .jacksonProperties = jacksonProperties ;
169+ }
141170
142171 @ Bean
143- StandardJsonMapperBuilderCustomizer standardJsonMapperBuilderCustomizer (JacksonProperties jacksonProperties ,
144- ObjectProvider <JacksonModule > modules ) {
145- return new StandardJsonMapperBuilderCustomizer (jacksonProperties , modules .stream ().toList ());
172+ StandardJsonFactoryBuilderCustomizer standardJsonFactoryBuilderCustomizer () {
173+ return new StandardJsonFactoryBuilderCustomizer (this .jacksonProperties );
174+ }
175+
176+ @ Bean
177+ StandardJsonMapperBuilderCustomizer standardJsonMapperBuilderCustomizer (ObjectProvider <JacksonModule > modules ) {
178+ return new StandardJsonMapperBuilderCustomizer (this .jacksonProperties , modules .stream ().toList ());
179+ }
180+
181+ static final class StandardJsonFactoryBuilderCustomizer
182+ extends AbstractFactoryBuilderCustomizer <JsonFactoryBuilder > implements JsonFactoryBuilderCustomizer {
183+
184+ StandardJsonFactoryBuilderCustomizer (JacksonProperties jacksonProperties ) {
185+ super (jacksonProperties );
186+ }
187+
188+ @ Override
189+ public void customize (JsonFactoryBuilder jsonFactoryBuilder ) {
190+ super .customize (jsonFactoryBuilder );
191+ }
192+
146193 }
147194
148195 static final class StandardJsonMapperBuilderCustomizer
@@ -189,17 +236,27 @@ public void customize(JsonMapper.Builder builder) {
189236 @ EnableConfigurationProperties (JacksonCborProperties .class )
190237 static class CborConfiguration {
191238
239+ private final JacksonProperties jacksonProperties ;
240+
241+ CborConfiguration (JacksonProperties jacksonProperties ) {
242+ this .jacksonProperties = jacksonProperties ;
243+ }
244+
192245 @ Bean
193246 @ ConditionalOnMissingBean
194- CBORMapper cborMapper (CBORMapper .Builder builder ) {
247+ CBORFactory cborFactory (List <CborFactoryBuilderCustomizer > customizers ) {
248+ CBORFactoryBuilder builder = CBORFactory .builder ();
249+ for (CborFactoryBuilderCustomizer customizer : customizers ) {
250+ customizer .customize (builder );
251+ }
195252 return builder .build ();
196253 }
197254
198255 @ Bean
199256 @ Scope (ConfigurableBeanFactory .SCOPE_PROTOTYPE )
200257 @ ConditionalOnMissingBean
201- CBORMapper .Builder cborMapperBuilder (List <CborMapperBuilderCustomizer > customizers ) {
202- CBORMapper .Builder builder = CBORMapper .builder ();
258+ CBORMapper .Builder cborMapperBuilder (CBORFactory factory , List <CborMapperBuilderCustomizer > customizers ) {
259+ CBORMapper .Builder builder = CBORMapper .builder (factory );
203260 customize (builder , customizers );
204261 return builder ;
205262 }
@@ -211,12 +268,37 @@ private void customize(CBORMapper.Builder builder, List<CborMapperBuilderCustomi
211268 }
212269
213270 @ Bean
214- StandardCborMapperBuilderCustomizer standardCborMapperBuilderCustomizer (JacksonProperties jacksonProperties ,
215- ObjectProvider <JacksonModule > modules , JacksonCborProperties cborProperties ) {
216- return new StandardCborMapperBuilderCustomizer (jacksonProperties , modules .stream ().toList (),
271+ @ ConditionalOnMissingBean
272+ CBORMapper cborMapper (CBORMapper .Builder builder ) {
273+ return builder .build ();
274+ }
275+
276+ @ Bean
277+ StandardCborFactoryBuilderCustomizer standardCborFactoryBuilderCustomizer () {
278+ return new StandardCborFactoryBuilderCustomizer (this .jacksonProperties );
279+ }
280+
281+ @ Bean
282+ StandardCborMapperBuilderCustomizer standardCborMapperBuilderCustomizer (ObjectProvider <JacksonModule > modules ,
283+ JacksonCborProperties cborProperties ) {
284+ return new StandardCborMapperBuilderCustomizer (this .jacksonProperties , modules .stream ().toList (),
217285 cborProperties );
218286 }
219287
288+ static final class StandardCborFactoryBuilderCustomizer
289+ extends AbstractFactoryBuilderCustomizer <CBORFactoryBuilder > implements CborFactoryBuilderCustomizer {
290+
291+ StandardCborFactoryBuilderCustomizer (JacksonProperties jacksonProperties ) {
292+ super (jacksonProperties );
293+ }
294+
295+ @ Override
296+ public void customize (CBORFactoryBuilder cborFactoryBuilder ) {
297+ super .customize (cborFactoryBuilder );
298+ }
299+
300+ }
301+
220302 static class StandardCborMapperBuilderCustomizer extends AbstractMapperBuilderCustomizer <CBORMapper .Builder >
221303 implements CborMapperBuilderCustomizer {
222304
@@ -244,17 +326,27 @@ public void customize(CBORMapper.Builder builder) {
244326 @ EnableConfigurationProperties (JacksonXmlProperties .class )
245327 static class XmlConfiguration {
246328
329+ private final JacksonProperties jacksonProperties ;
330+
331+ XmlConfiguration (JacksonProperties jacksonProperties ) {
332+ this .jacksonProperties = jacksonProperties ;
333+ }
334+
247335 @ Bean
248336 @ ConditionalOnMissingBean
249- XmlMapper xmlMapper (XmlMapper .Builder builder ) {
337+ XmlFactory xmlFactory (List <XmlFactoryBuilderCustomizer > customizers ) {
338+ XmlFactoryBuilder builder = XmlFactory .builder ();
339+ for (XmlFactoryBuilderCustomizer customizer : customizers ) {
340+ customizer .customize (builder );
341+ }
250342 return builder .build ();
251343 }
252344
253345 @ Bean
254346 @ Scope (ConfigurableBeanFactory .SCOPE_PROTOTYPE )
255347 @ ConditionalOnMissingBean
256- XmlMapper .Builder xmlMapperBuilder (List <XmlMapperBuilderCustomizer > customizers ) {
257- XmlMapper .Builder builder = XmlMapper .builder ();
348+ XmlMapper .Builder xmlMapperBuilder (XmlFactory xmlFactory , List <XmlMapperBuilderCustomizer > customizers ) {
349+ XmlMapper .Builder builder = XmlMapper .builder (xmlFactory );
258350 customize (builder , customizers );
259351 return builder ;
260352 }
@@ -266,9 +358,21 @@ private void customize(XmlMapper.Builder builder, List<XmlMapperBuilderCustomize
266358 }
267359
268360 @ Bean
269- StandardXmlMapperBuilderCustomizer standardXmlMapperBuilderCustomizer (JacksonProperties jacksonProperties ,
270- ObjectProvider <JacksonModule > modules , JacksonXmlProperties xmlProperties ) {
271- return new StandardXmlMapperBuilderCustomizer (jacksonProperties , modules .stream ().toList (), xmlProperties );
361+ @ ConditionalOnMissingBean
362+ XmlMapper xmlMapper (XmlMapper .Builder builder ) {
363+ return builder .build ();
364+ }
365+
366+ @ Bean
367+ StandardXmlFactoryBuilderCustomizer standardXmlFactoryBuilderCustomizer () {
368+ return new StandardXmlFactoryBuilderCustomizer (this .jacksonProperties );
369+ }
370+
371+ @ Bean
372+ StandardXmlMapperBuilderCustomizer standardXmlMapperBuilderCustomizer (ObjectProvider <JacksonModule > modules ,
373+ JacksonXmlProperties xmlProperties ) {
374+ return new StandardXmlMapperBuilderCustomizer (this .jacksonProperties , modules .stream ().toList (),
375+ xmlProperties );
272376 }
273377
274378 @ Configuration (proxyBeanMethods = false )
@@ -291,6 +395,20 @@ public void customize(XmlMapper.Builder builder) {
291395
292396 }
293397
398+ static final class StandardXmlFactoryBuilderCustomizer
399+ extends AbstractFactoryBuilderCustomizer <XmlFactoryBuilder > implements XmlFactoryBuilderCustomizer {
400+
401+ StandardXmlFactoryBuilderCustomizer (JacksonProperties jacksonProperties ) {
402+ super (jacksonProperties );
403+ }
404+
405+ @ Override
406+ public void customize (XmlFactoryBuilder xmlFactoryBuilder ) {
407+ super .customize (xmlFactoryBuilder );
408+ }
409+
410+ }
411+
294412 static class StandardXmlMapperBuilderCustomizer extends AbstractMapperBuilderCustomizer <XmlMapper .Builder >
295413 implements XmlMapperBuilderCustomizer {
296414
@@ -344,6 +462,46 @@ private boolean isPropertyNamingStrategyField(Field candidate) {
344462
345463 }
346464
465+ abstract static class AbstractFactoryBuilderCustomizer <B extends DecorableTSFBuilder <?, ?>> implements Ordered {
466+
467+ private final JacksonProperties jacksonProperties ;
468+
469+ AbstractFactoryBuilderCustomizer (JacksonProperties jacksonProperties ) {
470+ this .jacksonProperties = jacksonProperties ;
471+ }
472+
473+ @ Override
474+ public int getOrder () {
475+ return 0 ;
476+ }
477+
478+ protected void customize (B builder ) {
479+ Constraints constraints = this .jacksonProperties .getFactory ().getConstraints ();
480+ builder .streamReadConstraints (readConstraintsFrom (constraints .getRead ()));
481+ builder .streamWriteConstraints (writeConstraintsFrom (constraints .getWrite ()));
482+ }
483+
484+ private StreamReadConstraints readConstraintsFrom (Read read ) {
485+ PropertyMapper map = PropertyMapper .get ();
486+ StreamReadConstraints .Builder constraintsBuilder = StreamReadConstraints .builder ();
487+ map .from (read ::getMaxDocumentLength ).to (constraintsBuilder ::maxDocumentLength );
488+ map .from (read ::getMaxNameLength ).to (constraintsBuilder ::maxNameLength );
489+ map .from (read ::getMaxNestingDepth ).to (constraintsBuilder ::maxNestingDepth );
490+ map .from (read ::getMaxNumberLength ).to (constraintsBuilder ::maxNumberLength );
491+ map .from (read ::getMaxStringLength ).to (constraintsBuilder ::maxStringLength );
492+ map .from (read ::getMaxTokenCount ).to (constraintsBuilder ::maxTokenCount );
493+ return constraintsBuilder .build ();
494+ }
495+
496+ private StreamWriteConstraints writeConstraintsFrom (Write write ) {
497+ PropertyMapper map = PropertyMapper .get ();
498+ StreamWriteConstraints .Builder constraintsBuilder = StreamWriteConstraints .builder ();
499+ map .from (write ::getMaxNestingDepth ).to (constraintsBuilder ::maxNestingDepth );
500+ return constraintsBuilder .build ();
501+ }
502+
503+ }
504+
347505 abstract static class AbstractMapperBuilderCustomizer <B extends MapperBuilder <?, ?>> implements Ordered {
348506
349507 private final JacksonProperties jacksonProperties ;
0 commit comments