Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@JsonUnwrapped is still broken since 2.5 #2879

Open
wingsofovnia opened this issue Jan 29, 2025 · 1 comment
Open

@JsonUnwrapped is still broken since 2.5 #2879

wingsofovnia opened this issue Jan 29, 2025 · 1 comment

Comments

@wingsofovnia
Copy link

wingsofovnia commented Jan 29, 2025

Describe the bug

Since @JsonUnwrapped has been broken in 2.6.0 I still not able to make @JsonUnwrapped work with my Kotlin data classes despite numerous fixes:

To Reproduce

data class ContactCreateRequest(
    @JsonUnwrapped
    val person: Person,

    @Schema(required = false)
    @JsonProperty("labels", required = false)
    val labels: List<String>? = null,
)

data class Person(
    @Schema(required = true, example = "Oscar Claude Monet")
    @JsonProperty("name", required = true)
    val name: String,

    @Schema(example = "+38051231412")
    @JsonProperty("phone")
    val phone: String? = null,

    @Schema(required = true, example = "oscar.monet@lafrance.fr")
    @JsonProperty(value = "email", required = true)
    val email: String,
)

This example in a sample Spring Boot project:

Dependencies

  • Kotlin 2.1.10
  • org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4
  • org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.4
  • org.springframework.boot:spring-boot-....:3.4.2

Expected Behavior (v2.5.0)
Image

Actual Behavior (v2.8.4)
Image

@wingsofovnia
Copy link
Author

wingsofovnia commented Jan 29, 2025

I did some research and figured out that while this does not work:

data class ContactCreateRequest(
	@JsonUnwrapped
	val person: Person,
)

this does:

data class ContactCreateRequest(
	@field:JsonUnwrapped // Apply @JsonUnwrapped to field
	val person: Person,
)

The decompiled byte code for those look like that:

public final class ContactCreateRequest {
   @NotNull
   private final Person person;

   public ContactCreateRequest(@JsonUnwrapped @NotNull Person person) {
      Intrinsics.checkNotNullParameter(person, "person");
      super();
      this.person = person;
   }
   
   @NotNull
   public final Person getPerson() {
      return this.person;
   }
// ....
}

vs

public final class ContactCreateRequest {
   @JsonUnwrapped
   @NotNull
   private final Person person;

   public ContactCreateRequest(@NotNull Person person) {
      Intrinsics.checkNotNullParameter(person, "person");
      super();
      this.person = person;
   }
   
   @NotNull
   public final Person getPerson() {
      return this.person;
   }
// ....
}

Funny thing is that if I try to replicate the first approach with pure Java, @JsonCreators with @JsonUnwrapped are not supported yet:

public class Book {
    private final Author author;
    private final String title;

    public Book(@JsonUnwrapped(prefix = "author_") Author author, @JsonProperty("title") String title) {
        this.author = author;
        this.title = title;
    }
}
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Invalid type definition for type `com.example.demo.Book`: 
   Cannot define Creator parameter 0 as `@JsonUnwrapped`: combination not yet supported

This must be the Kotlin plugin doing some magic on top of default Jackson. This however is expected to change in the next Jackson minor release with FasterXML/jackson-databind#1467 merge.

Given that in this example ContactCreateRequest used for request body, it is deserialisation "view" that should be considered. It looks like the lookup for @JsonUnwrapped since 2.5.0 has been reduced to looking at field annotations only.
Both for Kotlin support and upcoming support of creators + unwrapped, I believe springdoc should bring the support back at looking for @JsonUnwrapped in creators and should distinguish between deserialisation and serialisation configurations.

@wingsofovnia wingsofovnia changed the title @JsonUnwrapped is not still broken since 2.5 @JsonUnwrapped behaves differently in Kotlin since 2.6 Jan 29, 2025
@wingsofovnia wingsofovnia changed the title @JsonUnwrapped behaves differently in Kotlin since 2.6 @JsonUnwrapped is not still broken since 2.5 Jan 29, 2025
@wingsofovnia wingsofovnia changed the title @JsonUnwrapped is not still broken since 2.5 @JsonUnwrapped is still broken since 2.5 Jan 29, 2025
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

No branches or pull requests

1 participant