Home > Software design >  InvalidTypeIdException during deserialization with com.fasterxml.jackson.databind.ObjectMapper
InvalidTypeIdException during deserialization with com.fasterxml.jackson.databind.ObjectMapper

Time:03-10

I am trying to deserialize object using com.fasterxml.jackson.databind doing this way:

val restoredProject = validationSessionHelperImpl.objectMapper2.readValue<com.fmetric.validation.api.Project>(validationData.projectJSON!!)

detailed code here https://gist.github.com/iva-nova-e-katerina/f09cce0ade8a9b9a69ab9b52cbb1b0ea and got following error:

   com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve type id 'java.util.ArrayList' as a subtype of `java.util.List<com.fmetric.regulation.api.data.property.PropertyType>`: Configured `PolymorphicTypeValidator` (of type `com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator`) denied resolution
 at [Source: (StringReader); line: 1, column: 237] (through reference chain: com.fmetric.validation.api.Project["rootBrick"]->com.fmetric.validation.api.Brick["type"]->com.fmetric.regulation.api.data.brick.BrickTypeFull["propertyTypes"])

    at com.fasterxml.jackson.databind.exc.InvalidTypeIdException.from(InvalidTypeIdException.java:43)
    at

The source JSON string is here https://gist.github.com/iva-nova-e-katerina/fa5ce8ddb03fb9db2b0dde930a6dbd5d

I must tell you something about classes hierarchy

data class Brick(
    val id: UUID?,
    val name: String,
    val type: BrickType,
    val propertyValues: List<ProjectBrickPropertyValue<*>>,
)

open class BrickType(
    open val id: UUID?,
    open val name: String?
) 

class BrickTypeFull(
     id: UUID?,
     name: String?,
     val propertyTypes: List<PropertyType>?
) : BrickType (id,name){

This issue is related to another my question UnrecognizedPropertyException during deserialization with com.fasterxml.jackson.databind.ObjectMapper

Could you help me to serialize/deserialize an object aggregated with the object of inherited type BrickTypeFull ?

CodePudding user response:

Here is a complete example

package com.example

import com.fasterxml.jackson.annotation.JsonIgnoreProperties
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator
import com.fasterxml.jackson.module.kotlin.KotlinModule
import java.util.*

const val payload: String = """
{
    "id":"f0156c1d-238b-4cfa-a5ba-17a3e2c9dc55",
    "name":"Здание",
    "type":["com.example.BrickTypeFull",{
        "id":"24073daa-4193-4f16-bed2-d8ef226a8715",
        "name":"Здание",
        "propertyTypes":["java.util.ArrayList",[
            {"id":"ed4e58f5-722e-4752-bf24-1b34dc5fdcd5","category":"BOOLEAN","name":"Cтатус архитектурного памятника","description":"Статус архитектурного памятника","brickTypeId":"24073daa-4193-4f16-bed2-d8ef226a8715","regulationId":null,"dictionaryValueId":null,"options":null},
            {"id":"ed4e58f5-722e-4752-bf24-1b34dc5fdcd5","category":"BOOLEAN","name":"Cтатус архитектурного памятника","description":"Статус архитектурного памятника","brickTypeId":"24073daa-4193-4f16-bed2-d8ef226a8715","regulationId":null,"dictionaryValueId":null,"options":null}
        ]]
    }]
}
"""

data class Brick(
    val id: UUID?,
    val name: String,
    val type: BrickType,
)

open class BrickType(
    open val id: UUID?,
    open val name: String?
)

class BrickTypeFull(
    id: UUID?,
    name: String?,
    val propertyTypes: List<PropertyType>?
) : BrickType(id, name)

@JsonIgnoreProperties(ignoreUnknown = true)
data class PropertyType(
    val id: UUID,
    val category: String,
    val name: String,
    val description: String,
    val brickTypeId: UUID,
    val regulationId: UUID?,
    val dictionaryValueId: UUID?,
)

fun main(args: Array<String>) {
    ObjectMapper().apply {
        registerModule(KotlinModule.Builder().build())
        activateDefaultTyping(
            BasicPolymorphicTypeValidator.builder()
                .allowIfSubType("com.example")
                .allowIfSubType("java.util.ArrayList")
                .build(),
            ObjectMapper.DefaultTyping.NON_FINAL
        )
    }.also {
        val result = it.readerFor(Brick::class.java).readValue<Brick>(payload)
        println((result.type as BrickTypeFull).propertyTypes?.get(0))
    }
}

Probably you forgot to add .allowIfSubType("java.util.ArrayList") to your deserialiser.

CodePudding user response:

Deserialization works with following Validator

   val ptv: PolymorphicTypeValidator = BasicPolymorphicTypeValidator.builder()
        .allowIfSubType("com.fmetric.regulation.api.data.brick")
        .allowIfSubType("java.util.ArrayList")
        .build()
  • Related