Skip to content

InvalidTypeIdException Cannot deduce unique subtype #3577

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jmjava opened this issue Aug 19, 2022 · 9 comments
Closed

InvalidTypeIdException Cannot deduce unique subtype #3577

jmjava opened this issue Aug 19, 2022 · 9 comments
Labels
polymorphic-deduction Issues related to "Id.DEDUCTION" mode of `@JsonTypeInfo`

Comments

@jmjava
Copy link

jmjava commented Aug 19, 2022

I am attempting to use deduction with 2.13.3

I have a set of classes that have a largish set of properties (over 10) and sometimes only differ by one or two fields

Some of the classes are able to deserialize correctly but others get this exception

com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve subtype of [simple type, class xxxxx]: Cannot deduce unique subtype of oxxxxxxx (3 candidates match)

If I step debug the code I can see this before the error is thrown. It appears there is something called subTypeFingerprints that shows this

Screen Shot 2022-08-19 at 7 12 52 PM

What is interesting is that the error says 3 candidates match and as you can see from the picture above... there are 3 candidates that match up to the value of 11...

is there a limit on the number of comparisons that are made? As you can see the fingerprints seem to indicate that a deduction should be possible, yet I am getting this error

-john

@jmjava jmjava added the to-evaluate Issue that has been received but not yet evaluated label Aug 19, 2022
@jmjava
Copy link
Author

jmjava commented Aug 20, 2022

in AsDeductionTypedFromObject i see "END_OBJECT" from the JsonParser but the desired object has more fields...

in the method createParser i see this - is there some limit to the length of the "content" ???? Can this be changed or configured?

public JsonParser createParser(String content) throws IOException, JsonParseException {
    final int strLen = content.length();
    // Actually, let's use this for medium-sized content, up to 64kB chunk (32kb char)
    if ((_inputDecorator != null) || (strLen > 0x8000) || !canUseCharArrays()) {
        // easier to just wrap in a Reader than extend InputDecorator; or, if content
        // is too long for us to copy it over
        return createParser(new StringReader(content));
    }
    IOContext ctxt = _createContext(_createContentReference(content), true);
    char[] buf = ctxt.allocTokenBuffer(strLen);
    content.getChars(0, strLen, buf, 0);
    return _createParser(buf, 0, strLen, ctxt, true);
}

@cowtowncoder
Copy link
Member

cowtowncoder commented Aug 20, 2022

No, there is no limit to number of Object properties that are read; length of content does not matter. What you see is just a simple optimization on whether to read contents of String using StringReader (for above 64k) or by copying contents into char[] and using parser that reads directly from there.
This has no relevance to higher level operations.

As to debugger; instead of looking at internal you might want to check whether existence of logical property values makes sense: what exception says it that with given properties, there are 3 types that could be matches and unique determination is not possible. Fingerprint simply means a bit set that indicates which properties have been seen for the current Object, and which types match (expect those properties).

To actually show a problem it'd be necessary to show type definitions; at this point description does not allow reproducing the issue.
For proof I guess it should be enough to show just 2 or 3 subtypes that are claimed to be ambiguous, along with input that should not indicate ambiguity. If there is a bug in handling, of course there may be other factors.
But a minimal reproduction would be optimal.

@cowtowncoder cowtowncoder removed the to-evaluate Issue that has been received but not yet evaluated label Aug 20, 2022
@TharinduMalinda
Copy link

TharinduMalinda commented Aug 20, 2022 via email

@jmjava
Copy link
Author

jmjava commented Aug 20, 2022

Sorry I can't send the actual type definitions for security reasons, I tried to explain what I have.

The payload that produces an error is a subset of the fields in two other subclasses - when I send payload with the subset json the logic stops at the field 12 (SHOWS END_OBJECT) and gives the message from this line in AsDeductionTypeDeserializer.java

String msgToReportIfDefaultImplFailsToo = String.format("Cannot deduce unique subtype of %s (%d candidates match)", ClassUtil.getTypeDescription(_baseType), candidates.size()); <-- At this point in the parsing there a 3 objects that have this set of fields 1-12 but 1 has exactly 12 fields and the other 2 have more fields

SubClassA
field1
field2
field3
...
field12

SubClassB
field1
field2
field3
..
field12
field13
fiedl14

SubClassC
field1
field2
field3
..
fiedl12
field15

Note: The subtypeFingerprints seems to show the same thing. Matching up to 11 (12th field) for 3 objects.

image

@cowtowncoder cowtowncoder added the polymorphic-deduction Issues related to "Id.DEDUCTION" mode of `@JsonTypeInfo` label Aug 20, 2022
@cowtowncoder
Copy link
Member

Ok then maybe this is just misunderstanding of the Deduction process: it does NOT take into account ABSENCE of fields, only presence.
See #2976 for more details

So if there are 3 types that have fields presented so far, it does not matter if 2 of them could also accept other fields; this plays no part.

And while this is not something that could not be improved upon theoretically, the current implementation (see #43) is not easily extensible (AFAIK) to try to track absence (or maybe "coverage" information).
There has to be unique set of determining properties.

/cc @drekbour

@jmjava
Copy link
Author

jmjava commented Aug 20, 2022

Thanks for your help help. So I guess I need to find another solution for our mappings.

We were trying to apply Deduction to solve a problem where a "parent" object contains a "data" field and the type of the data field is in the parent

Something like this:

Parent:
type: Enum which determine type of field "data"
data:
field1
field2
field3
etc.

I have seen working Jackson examples of where the type is contained inside the data field. (See below) Unfortunately, we are not in control of the data format and the requirements are to handle a format as above.

Parent:
data:
type: Enum which determine type of field "data"
field1
field2
field3
etc.

Is there any way to get Jackson to look for the type field in the parent object? We have not been able to find a working solution for this.

Again, thanks for your help.

-john

@cowtowncoder
Copy link
Member

cowtowncoder commented Aug 20, 2022

@jmjava This sounds like you'd want to use specific kind of alternate inclusion mechanism for @JsonTypeInfo.
So, instead of most commonly used As.PROPERTY (in which type identifier property is "inside" of value Object), As.EXTERNAL_PROPERTY has it alongside "parent" Object. Hence it's "external" vs "internal".

public class Parent {
   @JsonTypeInfo(include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property="type")
   public BaseType value;

   // you may have property with name "type", or not 
}

// Matches structure like:

{
   "type" : "MySubType",
   "value" {
       "property1" : "value1",
       "property2" : "value2"
  }
}

and I was trying to see if there was good documentation outside of Javadocs without finding it.
But this:

https://www.faqcode4u.com/faq/83582/java-jackson-polymorphic-json-deserialization-of-an-object-with-an-interface-pr

has one answer. But the other point (aside from using different value for include property) is that @JsonTypeInfo MUST be on property that contains polymorphic object and NOT on class definition (other inclusion mechanisms allow either choice).

@jmjava
Copy link
Author

jmjava commented Aug 21, 2022

@cowtowncoder THANK YOU VERY MUCH!!!! I will give this a try.

-john

@cowtowncoder
Copy link
Member

(sounds like use of As.EXTERNAL_PROPERTY was what was needed -- closing. There is also an existing issue wrt Deduction not taking into account absence of property.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
polymorphic-deduction Issues related to "Id.DEDUCTION" mode of `@JsonTypeInfo`
Projects
None yet
Development

No branches or pull requests

3 participants