-
-
Notifications
You must be signed in to change notification settings - Fork 138
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
[Avro] Fix custom deserializers not being used #71
[Avro] Fix custom deserializers not being used #71
Conversation
@@ -57,6 +54,13 @@ public Object deserializeTypedFromScalar(JsonParser p, DeserializationContext ct | |||
|
|||
@Override | |||
public Object deserializeTypedFromAny(JsonParser p, DeserializationContext ctxt) throws IOException { | |||
AnnotationIntrospector ai = ctxt.getAnnotationIntrospector(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like instead of having the type deserializer look for custom deserializers, there should be some way to avoid using the type deserializer at all for properties that have custom deserializers - but I don't know where that check needs to be made.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The whole idea of type (de)serializers is that they can be composed with content (de)serializers and work independently. But use of type (de)serializers is inferred from polymorphic handling, so perhaps that should not be enabled if no type handling is desired?
@@ -138,6 +138,13 @@ public void skipString() throws IOException { | |||
@Override | |||
public ByteBuffer readBytes(ByteBuffer old) throws IOException { | |||
consumeToken(JsonToken.VALUE_EMBEDDED_OBJECT); | |||
byte[] value = _parser.getBinaryValue(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bugfix: Caller expecting old
to be populated with data and not actually using the return value needs to be supported.
@@ -74,8 +76,67 @@ protected CustomComponent read(Object reuse, Decoder in) throws IOException { | |||
|
|||
} | |||
|
|||
protected Wrapper wrapper; | |||
public static class UuidAsBytesAvroEncoding extends CustomEncoding<UUID> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The original format of this test meant that if the custom deserializer wasn't picked up, Jackson was still flexible enough that it would pass the test because it could read what it wrote. This UuidAsBytesAvroEncoding
actually changes the serialized format, which means this will now break if the custom serializers/deserializers are ignored.
Ouch. Type (de)serializers absolute and positively should never be used for non-polymorphic properties, so that should not be done. I guess I did not read the patch carefully enough. |
@@ -57,6 +54,13 @@ public Object deserializeTypedFromScalar(JsonParser p, DeserializationContext ct | |||
|
|||
@Override | |||
public Object deserializeTypedFromAny(JsonParser p, DeserializationContext ctxt) throws IOException { | |||
AnnotationIntrospector ai = ctxt.getAnnotationIntrospector(); | |||
if (ai != null && _property != null) { | |||
JsonDeserializer<?> deser = ctxt.deserializerInstance(_property.getMember(), ai.findDeserializer(_property.getMember())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is extremely inefficient as well; usually deserializers are cached, and if this is not done much (most?) of the time is spent on fetching and contextualizing deserializer...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this was more in the "it worked" category rather than the "this is how to fix it" category.
I think I found a better solution, about to push up some changes.
old.put(value); | ||
old.flip(); | ||
return old; | ||
} | ||
return ByteBuffer.wrap(_parser.getBinaryValue()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should pass value
, and not call accessor again.
ce90424
to
c4cf826
Compare
@@ -161,6 +162,10 @@ public Object findSerializer(Annotated a) { | |||
} | |||
|
|||
protected TypeResolverBuilder<?> _findTypeResolver(MapperConfig<?> config, Annotated ann, JavaType baseType) { | |||
// If there's a custom deserializer, then it's responsible for handling any type information | |||
if (config.getAnnotationIntrospector().findDeserializer(ann) != null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the best way to do this check?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don' t think this approach makes sense: annotations are just one way to register deserializers; modules register others. But beyond this, as I said, type handlers and content handlers are not meant to be aware of each other.
Ok, so, yeah. I don't think |
@@ -138,7 +138,14 @@ public void skipString() throws IOException { | |||
@Override | |||
public ByteBuffer readBytes(ByteBuffer old) throws IOException { | |||
consumeToken(JsonToken.VALUE_EMBEDDED_OBJECT); | |||
return ByteBuffer.wrap(_parser.getBinaryValue()); | |||
byte[] value = _parser.getBinaryValue(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about I merge this separate from PR as it seems legit separate from other question.
c4cf826
to
eb812cf
Compare
eb812cf
to
c2c2040
Compare
Following the discussion on #60, the recent changes to master have fixed this problem. I have updated this PR to include just the tests to catch the issue if it appears again. |
Makes sense, merged. |
Found an issue that wasn't caught by one of the test suites.
Turns out because I'm always returning a
TypeDeserializer
for every property, Jackson doesn't use any custom deserializers that are registered for that property. I have a workaround here that checks for one and uses it instead, but I think there's a better way whereby I don't return aTypeResolverBuilder
for properties that have custom deserializers, but I couldn't get that working. What's the proper way to fix this?