From b7129b92e04408a2985d489cb3cccc8b72c2114d Mon Sep 17 00:00:00 2001 From: Vladislav Kopnin Date: Wed, 28 Oct 2026 00:02:01 +0300 Subject: [PATCH] =?UTF-8?q?fix(json):=20=D0=BF=D1=80=D0=B8=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D1=8F=D1=82=D1=8C=20Kotlin-=D0=BC=D0=BE=D0=B4=D1=83?= =?UTF-8?q?=D0=BB=D1=8C=20Jackson=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ysu/lms/academic/config/JacksonConfig.kt | 17 ++++++++++++++++ .../ysu/lms/identity/config/JacksonConfig.kt | 20 +++++++++++++++++++ .../identity/roster/TeacherIntegrationTest.kt | 15 ++++++++++++++ .../ysu/lms/progress/config/JacksonConfig.kt | 17 ++++++++++++++++ .../ru/ysu/lms/web/config/JacksonConfig.kt | 17 ++++++++++++++++ 5 files changed, 86 insertions(+) create mode 100644 services/academic-service/src/main/kotlin/ru/ysu/lms/academic/config/JacksonConfig.kt create mode 100644 services/identity-service/src/main/kotlin/ru/ysu/lms/identity/config/JacksonConfig.kt create mode 100644 services/progress-service/src/main/kotlin/ru/ysu/lms/progress/config/JacksonConfig.kt create mode 100644 web/src/main/kotlin/ru/ysu/lms/web/config/JacksonConfig.kt diff --git a/services/academic-service/src/main/kotlin/ru/ysu/lms/academic/config/JacksonConfig.kt b/services/academic-service/src/main/kotlin/ru/ysu/lms/academic/config/JacksonConfig.kt new file mode 100644 index 0000000..e31d4d2 --- /dev/null +++ b/services/academic-service/src/main/kotlin/ru/ysu/lms/academic/config/JacksonConfig.kt @@ -0,0 +1,17 @@ +package ru.ysu.lms.academic.config + +import org.springframework.boot.jackson.autoconfigure.JsonMapperBuilderCustomizer +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import tools.jackson.module.kotlin.KotlinModule + +/** Jackson 3: без Kotlin-модуля DTO с default-значениями требуют все поля JSON. */ +@Configuration +class JacksonConfig { + @Bean + fun kotlinModule(): KotlinModule = KotlinModule.Builder().build() + + @Bean + fun kotlinJsonCustomizer(): JsonMapperBuilderCustomizer = + JsonMapperBuilderCustomizer { builder -> builder.addModule(KotlinModule.Builder().build()) } +} diff --git a/services/identity-service/src/main/kotlin/ru/ysu/lms/identity/config/JacksonConfig.kt b/services/identity-service/src/main/kotlin/ru/ysu/lms/identity/config/JacksonConfig.kt new file mode 100644 index 0000000..52ff66e --- /dev/null +++ b/services/identity-service/src/main/kotlin/ru/ysu/lms/identity/config/JacksonConfig.kt @@ -0,0 +1,20 @@ +package ru.ysu.lms.identity.config + +import org.springframework.boot.jackson.autoconfigure.JsonMapperBuilderCustomizer +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import tools.jackson.module.kotlin.KotlinModule + +/** + * Jackson 3 не подхватывает Kotlin-модуль автоматически в Spring Boot 4: + * без него DTO с default-значениями требуют все поля в JSON. + */ +@Configuration +class JacksonConfig { + @Bean + fun kotlinModule(): KotlinModule = KotlinModule.Builder().build() + + @Bean + fun kotlinJsonCustomizer(): JsonMapperBuilderCustomizer = + JsonMapperBuilderCustomizer { builder -> builder.addModule(KotlinModule.Builder().build()) } +} diff --git a/services/identity-service/src/test/kotlin/ru/ysu/lms/identity/roster/TeacherIntegrationTest.kt b/services/identity-service/src/test/kotlin/ru/ysu/lms/identity/roster/TeacherIntegrationTest.kt index 93cabeb..ba4b172 100644 --- a/services/identity-service/src/test/kotlin/ru/ysu/lms/identity/roster/TeacherIntegrationTest.kt +++ b/services/identity-service/src/test/kotlin/ru/ysu/lms/identity/roster/TeacherIntegrationTest.kt @@ -65,6 +65,8 @@ class TeacherIntegrationTest { @Autowired lateinit var context: WebApplicationContext + @Autowired lateinit var jsonMapper: tools.jackson.databind.json.JsonMapper + private val mockMvc: MockMvc by lazy { MockMvcBuilders .webAppContextSetup(context) @@ -184,6 +186,19 @@ class TeacherIntegrationTest { } } + @Test + fun `student creation accepts omitted optional json fields`() { + val request = + jsonMapper.readValue( + """{"studentNo":"api-student-1","lastName":"Тестов"}""", + CreateStudentRequest::class.java, + ) + assertEquals("api-student-1", request.studentNo) + assertEquals("Тестов", request.lastName) + assertEquals("", request.firstName) + assertEquals("", request.basis) + } + private fun student(login: String): Account = Account( login = login, diff --git a/services/progress-service/src/main/kotlin/ru/ysu/lms/progress/config/JacksonConfig.kt b/services/progress-service/src/main/kotlin/ru/ysu/lms/progress/config/JacksonConfig.kt new file mode 100644 index 0000000..4a2aa62 --- /dev/null +++ b/services/progress-service/src/main/kotlin/ru/ysu/lms/progress/config/JacksonConfig.kt @@ -0,0 +1,17 @@ +package ru.ysu.lms.progress.config + +import org.springframework.boot.jackson.autoconfigure.JsonMapperBuilderCustomizer +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import tools.jackson.module.kotlin.KotlinModule + +/** Jackson 3: без Kotlin-модуля DTO с default-значениями требуют все поля JSON. */ +@Configuration +class JacksonConfig { + @Bean + fun kotlinModule(): KotlinModule = KotlinModule.Builder().build() + + @Bean + fun kotlinJsonCustomizer(): JsonMapperBuilderCustomizer = + JsonMapperBuilderCustomizer { builder -> builder.addModule(KotlinModule.Builder().build()) } +} diff --git a/web/src/main/kotlin/ru/ysu/lms/web/config/JacksonConfig.kt b/web/src/main/kotlin/ru/ysu/lms/web/config/JacksonConfig.kt new file mode 100644 index 0000000..5986b1f --- /dev/null +++ b/web/src/main/kotlin/ru/ysu/lms/web/config/JacksonConfig.kt @@ -0,0 +1,17 @@ +package ru.ysu.lms.web.config + +import org.springframework.boot.jackson.autoconfigure.JsonMapperBuilderCustomizer +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import tools.jackson.module.kotlin.KotlinModule + +/** Jackson 3: без Kotlin-модуля DTO с default-значениями требуют все поля JSON. */ +@Configuration +class JacksonConfig { + @Bean + fun kotlinModule(): KotlinModule = KotlinModule.Builder().build() + + @Bean + fun kotlinJsonCustomizer(): JsonMapperBuilderCustomizer = + JsonMapperBuilderCustomizer { builder -> builder.addModule(KotlinModule.Builder().build()) } +}