spring-projects / spring-projects/spring-boot

Kotlin Serialization does not back off when JSON-B is the only JSON converter

Open
#50,953 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status: waiting-for-triage
Dominant language
Java
Stars
81.5k
Forks
42.7k
Avg merge
2d 4h
Merged PRs (30d)
65

Description

KotlinSerializationJsonConvertersCustomizer gives the Kotlin Serialization converter a broad (type) -> true predicate unless one of its Jackson 3, Jackson 2, or Gson classpath checks matches. JSON-B is not among those checks:

boolean hasAnyJsonSupport = ClassUtils.isPresent("tools.jackson.databind.json.JsonMapper", classLoader)
        || ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader)
        || ClassUtils.isPresent("com.google.gson.Gson", classLoader);

When JSON-B and Kotlin Serialization are configured together without Jackson or Gson, the Kotlin converter claims every type for application/json and, being ordered ahead of JSON-B, handles non-@Serializable types that JsonbHttpMessageConverter would otherwise serialize. This doesn't match the "when no alternative JSON converter is available" intent of #48070.

Reproduction: with only kotlinx-serialization-json and a JSON-B provider on the classpath (no Jackson/Gson). With this setup, the auto-configured Kotlin converter is given its broad (type) -> true predicate and therefore reports that it can write Map as application/json, so it wins over JsonbHttpMessageConverter for non-@Serializable types. The same client and server customizer feeds MVC, RestTemplate, and RestClient; the reactive codec side has no JSON-B codec and is not affected.

This is a regression from 4.0.0 to 4.0.1. The original fix for #48070 (58cdf71) decided the predicate by scanning the registered HttpMessageConverter beans for one supporting application/json, which included JSON-B. The client/server split in 4.0.1 (50f64f) replaced that with the Jackson/Jackson2/Gson classpath check above, dropping JSON-B. It remains in 4.0.x, 4.1.x, and main.

A plain jakarta.json.bind.Jsonb classpath check needs care: JsonbAutoConfiguration requires JSON-B and JSON-P provider resources before it creates a Jsonb bean (covered by JsonbAutoConfigurationWithNoProviderTests), whereas Spring Framework's default converter detection checks for the JSON-B API alone. The API-only case therefore needs separate consideration. What is the right signal to reflect the JSON-B converter's actual availability in the Kotlin predicate?

If this direction is appropriate, I can prepare a small patch with tests covering both the active JSON-B and API-only cases.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in KotlinSerializationJsonConvertersCustomizer and compare its classpath checks with JSON-B converter availability. Read JsonbAutoConfigurationWithNoProviderTests first, then trace how the customizer feeds MVC, RestTemplate, and RestClient. Done means tests cover both an active JSON-B provider and the API-only case, without affecting reactive codecs.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, kotlin, spring-boot
Domain
api, backend, testing
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.