jackson-kotlin-serialization-specialist

โดย kotlin

วินิจฉัยและออกแบบพฤติกรรมการซีเรียลไลซ์และดีซีเรียลไลซ์ JSON สำหรับ Kotlin ร่วมกับ Jackson ในแอปพลิเคชัน Spring ใช้เมื่อ DTO ไม่สามารถดีซีเรียลไลซ์ได้ ค่าเริ่มต้น…

npx skills add https://github.com/kotlin/kotlin-backend-agent-skills --skill jackson-kotlin-serialization-specialist

Jackson Kotlin Serialization Specialist

Source mapping: Tier 2 high-value skill derived from Kotlin_Spring_Developer_Pipeline.md (SK-08).

Mission

Make Kotlin plus Jackson behavior explicit, compatible, and testable. Treat wire-format correctness as a contract problem, not only a mapper-configuration problem.

Read First

  • The actual DTO or event model classes.
  • The exact failing JSON payload or expected payload examples.
  • ObjectMapper customizers, Spring Boot Jackson properties, and any per-client mapper overrides.
  • Build files to verify Jackson module alignment with Spring Boot and Kotlin versions.
  • The boundary where serialization matters: MVC, WebFlux, Kafka, Redis, persistence JSON column, or external HTTP client.

Diagnose In This Order

  1. Verify module presence and alignment:
    • jackson-module-kotlin
    • JavaTimeModule
    • other custom modules or serializers
  2. Verify constructor semantics:
    • default parameters
    • required parameters
    • nullable versus non-null
  3. Verify field presence semantics:
    • absent
    • present with null
    • present with value
  4. Verify naming, inclusion, and date-time strategy.
  5. Verify polymorphism or custom serializer behavior.
  6. Verify whether the real bug comes from a local mapper override rather than the global mapper.

Core Kotlin Rules

  • Keep DTOs immutable unless the project already has a strong alternative convention.
  • Do not switch val to var just to appease Jackson.
  • Do not add empty constructors to Kotlin DTOs as a workaround if the Kotlin module can model the contract correctly.
  • Treat nullable as a wire-contract decision, not a convenient escape hatch.
  • Be explicit about value classes, sealed hierarchies, and default parameter behavior.

Advanced Serialization Traps

  • Missing field and explicit null are not the same. For PATCH-like contracts, model tri-state semantics deliberately.
  • Default constructor values can silently hide client mistakes if the field should have been required.
  • @JsonInclude may improve payload size but can also erase signal that clients rely on.
  • Non-null primitives, FAIL_ON_NULL_FOR_PRIMITIVES, and Kotlin non-null types interact differently across payload shapes.
  • Sealed classes need stable, versionable type discriminators. Do not treat polymorphic type ids as an internal detail once they are on the wire.
  • Enum serialization by name, code, or custom object form is a public compatibility choice.
  • Date-time serialization must make timezone assumptions explicit. Instant, OffsetDateTime, and LocalDateTime are not interchangeable.
  • @JvmInline value class support may differ by Jackson version and serializer context. Verify scalar form and map-key behavior explicitly.
  • Global ObjectMapper changes can break unrelated endpoints or message consumers. Prefer narrow fixes when the issue is boundary-specific.

Boundary-Specific Nuances

  • MVC request and response mapping, Kafka message mapping, Redis payload mapping, and JSON-column mapping often use different mapper lifecycles even inside one codebase.
  • ObjectMapper.copy() can preserve most configuration while still drifting from future global changes. If a subsystem owns a private mapper, document that divergence.
  • Kotlin default parameters interact differently with creator annotations, mix-ins, and custom deserializers. If custom deserialization exists, verify constructor invocation explicitly.
  • Unknown enum handling, unknown-property handling, and coercion rules are compatibility decisions. A permissive setting may preserve old clients or may quietly accept garbage.
  • If the API is documented through OpenAPI or consumer contracts, make sure the documented nullability and actual wire behavior match. Kotlin type hints alone are not enough.

Expert Heuristics

  • If the same model is used on both inbound and outbound boundaries, check whether the optimal serializer settings are actually symmetrical. Often they are not.
  • If clients rely on partial update semantics, prefer an explicit patch model rather than trying to infer intent from ordinary DTO nullability.
  • If a serializer bug appears after a dependency upgrade, inspect feature defaults and module registration order before rewriting DTOs.
  • If compatibility matters, prove the fix with golden JSON examples or snapshot-style serialization tests, not only with one happy-path request.

Design Rules

  • Choose one naming strategy and document it.
  • Keep transport DTOs separate from persistence and domain objects when contract stability matters.
  • If payload evolution matters, favor additive fields and backward-compatible defaults over silent semantic changes.
  • If multiple serialization contexts exist, decide which behavior is global and which is boundary-specific.

Output Contract

Return these sections:

  • Observed behavior: what the current mapper does.
  • Contract expectation: what the wire format should mean.
  • Root cause: module, DTO, annotation, or mapper configuration issue.
  • Minimal fix: the smallest safe code or config change.
  • Compatibility risk: what existing clients or consumers might notice.
  • Verification: tests or sample payloads that prove the behavior.

Guardrails

  • Do not recommend random Jackson versions outside the repository's version authority.
  • Do not add global mapper behavior for a local one-off issue without explaining blast radius.
  • Do not hide a contract problem behind broad JsonNode or Map<String, Any> usage unless the boundary is intentionally untyped.
  • Do not rely on Jackson defaults when a stable external contract matters.

Quality Bar

A good run of this skill explains the wire contract, the mapper mechanics, and the compatibility impact in one coherent answer. A bad run sprinkles annotations until the example payload passes while leaving the contract ambiguous or unstable.

Skills เพิ่มเติมจาก kotlin

kotlin-backend-jpa-entity-mapping
kotlin
คลาสข้อมูลของ Kotlin เหมาะกับ DTO แต่เป็นอันตรายสำหรับเอนทิตี้ JPA Hibernate อาศัยความหมายของเอกลักษณ์ที่คลาสข้อมูลทำลาย: equals / hashCode ที่ครอบคลุมทุกฟิลด์ทำให้สมาชิกภาพของ Set / Map เสียหายหลังการเปลี่ยนแปลงสถานะ และ copy() ที่สร้างอัตโนมัติจะสร้างสำเนาที่แยกออกจากเอนทิตี้ที่ถูกจัดการ
kotlin-tooling-agp9-migration
kotlin
Android Gradle Plugin 9.0 ทำให้ปลั๊กอินแอปพลิเคชันและไลบรารีของ Android ไม่เข้ากันกับปลั๊กอิน Kotlin Multiplatform ในโมดูลเดียวกัน ทักษะนี้จะแนะนำคุณตลอดการย้ายข้อมูล
kotlin-tooling-cocoapods-spm-migration
kotlin
โยกย้ายโปรเจกต์ KMP จาก CocoaPods (kotlin("native.cocoapods")) ไปยัง Swift Package Manager (swiftPMDependencies DSL) — แทนที่ pod() ด้วย swiftPackage(),…
kotlin-tooling-immutable-collections-0-5-x-migration
kotlin
ย้ายโค้ด Kotlin (และ Java) จาก kotlinx.collections.immutable 0.3.x / 0.4.x ไปยังเวอร์ชันล่าสุด 0.5.x เส้นทาง 0.5.x เปลี่ยนชื่อทุกเมธอดที่คืนค่าสำเนาบน...
kotlin-tooling-java-to-kotlin
kotlin
แปลงไฟล์ต้นฉบับ Java เป็น Kotlin ที่เป็นธรรมชาติ โดยใช้วิธีการแปลงแบบ 4 ขั้นตอนที่มีระเบียบวินัย พร้อมตรวจสอบ 5 เงื่อนไขคงที่ในแต่ละขั้นตอน รองรับการแปลงที่คำนึงถึงเฟรมเวิร์ก ซึ่งจัดการเป้าหมายตำแหน่งของแอนโนเทชัน สำนวนของไลบรารี และการคงไว้ซึ่ง API
kotlin-tooling-native-build-performance
kotlin
วินิจฉัยและแก้ไขการคอมไพล์และการลิงก์ Kotlin/Native ที่ช้าในโปรเจกต์ Kotlin Multiplatform ที่กำหนดเป้าหมายเป็น iOS ใช้เมื่อผู้ใช้รายงานว่า iOS หรือ... ช้า
kotlin-spring-proxy-compatibility
kotlin
Diagnose and prevent Kotlin plus Spring proxy failures around `@Transactional`, `@Cacheable`, `@Async`, method security, retry, configuration proxies, and JPA…
ci-cd-containerization-advisor
kotlin
ออกแบบไปป์ไลน์การสร้าง อิมเมจ และการปรับใช้ที่ทำซ้ำได้สำหรับแอปพลิเคชัน Kotlin และ Spring รวมถึงการตรวจสอบ CI คอนเทนเนอร์แบบเลเยอร์ ความปลอดภัยในการเปิดตัว…