Oliver Payne
Oliver Payne

Reputation: 31

Spring MongoDb Custom serialization

We have a MongoDb database that receives interactions from both a Springboot application and a Scala-based lambda using Circe serialization. When Circe serializes a sealed trait that is implemented by several classes, this is the outcome:

{
  "ImplementationOfMySealedTrait": {
    "aField": "some-data"
  }
}

With Spring Data, serialization of a sealed interface has this result:

{
  "aField": "some-data"
}

I am looking for a way to configure my Springboot application so that data is saved to MongoDb in the format that Circe uses.

I have attempted to use a custom Converter to convert my object to and from a Map. This works, but its pretty tedious:

@WritingConverter
class ProfileWriteConverter : Converter<MySealedInterface, Map<String, Any?>> {
    override fun convert(source: MySealedInterface): Map<String, Any?> {
        return mapOf(
            source::class.java.simpleName to MapUtils.toMap(source)
        )
    }
}

@ReadingConverter
class ProfileReadConverter : Converter<Map<String, Any?>, MySealedInterface> {
    override fun convert(source: Map<String, Any?>): MySealedInterface {
        val implType = source.keys.first()
        val impl = source[implType] as Map<String, Any?>
        return when (profileType) {
            "ImplOne" -> Json.deserialize(profile, ImplOne::class)
            "ImplTwo" -> Json.deserialize(profile, ImplTwo::class)
            else -> throw IllegalArgumentException("Unknown type: $implType")
        }
    }
}

Naturally, I could see us needing to use this conversion with other sealed interfaces. So ideally this configuration would be easily repeatable for other fields. This could get there, but I still am not particularly fond of it as a solution. I would love for this to be a simple configuration change, but alas, I am not seeing anything like that.

Upvotes: 0

Views: 26

Answers (0)

Related Questions