skip to Main Content

I am working with the following structure:

class Family {
     //...
     Parent parent;
}

class Parent {
     //...
}

class ChildA extends Parent {
     //...
}

class ChildB extends Parent {
     //...
}

I am trying to deserialize a JSON object of type Family (with a Child object and not Parent), but I need to tweak one of the Child so I tried to start by pulling the Parent property from the Family object and then set it equal to a Child. However, the compiler was saying that I needed to typecast it, so I tried but then I got an error basically saying that I couldn’t typecast a superclass as a subclass, which makes sense.

I see now that the Family object gets deserialized with Parent only, and no subtypes. How can I deserialize Family with a Child property rather than a Parent type? I don’t understand because the Family object gets posted to the server with a Child object, but it gets deserialized only with the Parent properties.

Thanks

After doing some research, I came across what I believe might be part of the solution (although now I have a new problem)

I have revised my classes in the following way:

class Family {
     String address;
     Parent parent;
}

@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.PROPERTY,
        property = "type")
@JsonSubTypes({
        @JsonSubTypes.Type(value = ChildA.class, name = "A"),
        @JsonSubTypes.Type(value = ChildB.class, name = "B")
    })
class Parent {
     String parentAttribute;
}

@JsonSubType("A")
class ChildA extends Parent {
     String attributeA;
}
@JsonSubType("B")    
class ChildB extends Parent {
     String attributeB;
}

Now however, when I try to deserialize the Family class, I get the following error: com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve subtype of [simple type, class Family ]: missing type id property 'type' (for POJO property 'Parent')

There is no type field in any of my classes, I think this might have something to do with it.

Here is my JSON string that gets serialized:

{
     "Address": "123 Main St",
     "Parent": {
          "parentAttribute": "Mom",
          "attributeA": "Child A Type"
     }
}

Ideally, when I perform deserialization, I would do it on the same JSON string above, but the string above doesn’t include any type attributes. Is there a way I can sort of pre-process the deserialization and add an intermediary step (i.e. adding a type field?)

2

Answers


  1. Chosen as BEST ANSWER

    I was able to resolve this by taking advantage of the fact that one of the properties on the Parent class could be leveraged in the absence of a "type" field.

    The problem was that the JSON string being serialized does not include a "type" field, so rather than using:

    @JsonTypeInfo(
            use = JsonTypeInfo.Id.NAME,
            include = JsonTypeInfo.As.PROPERTY,
            property = "type")
    

    I changed "type" to that property name:

    @JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.PROPERTY,
        property = "theOtherProperty")
    

    This resolved my issues when attempting to deserialize the object. However, it is ultimately a workaround since it is not solving the original issue (doing some form of modification during the deserialization process to add an additional "type" field) but I am unsure of how to go about doing this anyhow.


  2. Before adding these annotations, I was able to serialize a POJO into a
    JSON string like this:

    {
         "Address": "123 Main St",
         "Parent": {
              "parentAttribute": "Mom",
              "attributeA": "Child A Type"
         }
     }
    

    Ideally, when I perform deserialization, I would do it on the same
    JSON string above, but the dto getting deserialized doesn’t use any of
    the Child types — I suppose it doesn’t know how to map which Child
    object so it just uses Parent, but my knowledge is limited here.

    As far as I know, this is not (easily) possible, I’m afraid. Not out-of-the-box and unlikely easily with custom deserialization code.

    Try to think from a deserializer point of view: You need something to destinguish JSON objects to map them to a Java class. Currently I only see the presence and absence of some child properties. This would need quite some logic to do the mapping.

    If you can change the JSON format, the easiest thing would be to add the property to the Parent which you specified in the following annotation (here: type):

    @JsonTypeInfo(
            use = JsonTypeInfo.Id.NAME,
            include = JsonTypeInfo.As.PROPERTY,
            property = "type")
    

    You can e.g. pass the value for this property hardcoded to the parent constructor to make sure serialized object has always the correct value.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search