如何在 Jackson 中复用自定义对象序列化器处理对象列表

可通过 `@jsonserialize(contentusing = ...)` 注解将已有的单对象序列化器(如 `studentserializer`)直接应用于集合字段,无需为 `list` 单独编写新序列化器。

在 Jackson 中,当您已为某个实体类(如 Student)实现了专用的 JsonSerializer,并希望在 List、MutableList 或其他集合类型中复用该逻辑时,无需额外定义 List 的专用序列化器。Jackson 提供了灵活的注解机制,允许您将单元素序列化器“提升”为集合内容的序列化器。

关键在于使用 @JsonSerialize 的 contentUsing 属性(而非 using),它专用于指定集合/数组/Map 值等“内容” 的序列化器:

class Course(
    var id: Long? = null,
    var name: String? = null,
    @JsonSerialize(contentUsing = StudentSerializer::class)
    var students: MutableList = mutableListOf()
)

✅ 此时,Jackson 在序列化 Course.students 时,会自动对列表中每个 Student 元素调用 StudentSerializer.serialize(),并按标准 JSON 数组格式输出(即 [ {...}, {...} ]),无需手动处理数组开始/结束标记。

⚠️ 注意事项:

  • contentUsing 仅作用于集合类字段的内容元素(如 List 中的 T),不适用于整个集合对象本身;
  • 若需统一为所有 List 类型全局启用该序列化器(而非逐字段标注),可注册为模块级序列化器:
    val module = SimpleModule().apply {
        setSerializer(List::class.java, StudentListSerializer()) // 需自定义包装器(较少见)
    }
    objectMapper.registerModule(module)

    但通常推荐显式标注 contentUsing,语义更清晰、维护性更强;

  • 确保 StudentSerializer 已通过 ObjectMapper 注册(如 objectMapper.registerModule(SimpleModule().addSerializer(Student::class.java, St

    udentSerializer()))),否则运行时会抛出 IllegalArgumentException。

总结:复用是 Jackson 的核心设计优势之一。借助 @JsonSerialize(contentUsing = ...),您既能保持序列化逻辑的单一职责(一个 StudentSerializer 覆盖所有使用场景),又能精准控制集合字段的序列化行为,大幅提升代码复用率与可维护性。