Skip to content

Conversation

@worldtiki
Copy link

@worldtiki worldtiki commented Nov 9, 2025

Description

This PR provides a simplified approach to customizing ObjectMapper beans used by Spring AI for JSON parsing operations, addressing feedback from PR #4833.

Problem

Issue #2494 identified several JSON parsing problems when using Spring AI with LLM-generated content such as unescaped control characters or date serialisation mismatch.
Users cannot configure Jackson features for their specific needs

Proposal

This PR refactors JsonParser and ModelOptionsUtils to support ObjectMapper injection through Spring's auto-configuration, allowing users to easily customise JSON processing behaviour.

Usage

@Configuration
public class MyJsonConfig {

    @Bean
    public ObjectMapper jsonParserObjectMapper() {
        return JsonMapper.builder()
            .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
            .enable(SerializationFeature.INDENT_OUTPUT)
            // ... custom configuration
            .build();
    }
}

@ericbottard
Copy link
Member

Hi @worldtiki,

thanks for your contribution!

While I can appreciate the need to provide means to customize ObjectMappers used in Spring AI, this PR seems too "overengineered" to me. IMO, there is no need for a dedicated maven module and autoconfiguration class for this. A change to existing configuration should hopefully suffice, keeping the approach of naming the OM beans.

Moreover, introducing ConfigurationProperties to drive the configuration of the OM is overkill. It merely reproduces what Jackson already provides and limits the configuration to what you've provided here. Just let users define their own OM bean if they want to, leveraging every Jackson feature they want if needed.

Lastly, I shall mention that complexifying the Jackson story in Spring AI before we migrate to Spring 7 / Boot 4 (which uses Jackson 3) may not be the best timing, so we should be very careful to not make things more complicated than they need be.

@worldtiki
Copy link
Author

Yeap that's fair @ericbottard.
Let me take a second look and try to simplify this.

worldtiki added a commit to worldtiki/spring-ai that referenced this pull request Nov 22, 2025
This change addresses feedback from PR spring-projects#4833 by providing a simplified
approach to customizing ObjectMapper beans used by Spring AI.

Key changes:
- Refactor JsonParser and ModelOptionsUtils to support ObjectMapper injection
- Add simple auto-configuration with @ConditionalOnMissingBean beans
- Remove complex ConfigurationProperties in favor of bean overrides
- Add new spring-ai-autoconfigure-json module

The implementation allows users to easily override ObjectMapper beans
by defining their own beans with the same name:
- jsonParserObjectMapper: for LLM response parsing
- modelOptionsObjectMapper: for model options handling

Default configuration includes:
- Lenient JSON parsing with unescaped control characters
- Date serialization as ISO strings instead of timestamps
- Empty string coercion to null for enums
- Accept empty strings as null objects

Fixes spring-projects#2494
@worldtiki worldtiki marked this pull request as draft November 22, 2025 15:34
@worldtiki worldtiki force-pushed the jackson branch 3 times, most recently from 1b0583c to b322184 Compare November 22, 2025 17:51
worldtiki added a commit to worldtiki/spring-ai that referenced this pull request Nov 29, 2025
This change addresses feedback from PR spring-projects#4833 by providing a simplified
approach to customizing ObjectMapper beans used by Spring AI.

Key changes:
- Refactor JsonParser and ModelOptionsUtils to support ObjectMapper injection
- Add simple auto-configuration with @ConditionalOnMissingBean beans
- Remove complex ConfigurationProperties in favor of bean overrides
- Add new spring-ai-autoconfigure-json module

The implementation allows users to easily override ObjectMapper beans
by defining their own beans with the same name:
- jsonParserObjectMapper: for LLM response parsing
- modelOptionsObjectMapper: for model options handling

Default configuration includes:
- Lenient JSON parsing with unescaped control characters
- Date serialization as ISO strings instead of timestamps
- Empty string coercion to null for enums
- Accept empty strings as null objects

Fixes spring-projects#2494
Signed-off-by: Daniel Albuquerque <daniel.albuquerque@teya.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants