Passing extra parameters to JsonDeserializers

319 views
Skip to first unread message

Péter Láng

unread,
Aug 3, 2015, 2:09:13 PM8/3/15
to jackson-user
Hello!

I'll try to describe my issue with the actual use-case:

I'm developing a generic REST service, where I have a "generic" JsonDeserializer implementation, which based on some request data (it's the endpoint address actually) delegates the task of deserialization to the appropriate "concrete" JsonDeserializer. It does so by calling jsonParser.readValueAs(actualClass). In reality this is even recursive, so I can parse arbitrary trees. All working fine. But now, what I'd like to do, is to collect all "not-so-fatal" parsing errors (that is, JsonMappingExceptions), instead of failing on the very first one. What I've have tried is to create a collection in the "generic" JsonDeserializer, put it in the DeserializationContext with setAttribute(..), expecting to be able to access it in the "concrete" deserializers later on, so I can put error descriptors into it. But that does not work, the collection is not in the attributes, I get NPEs. So I guess that's not what attributes are for, or the context's lifespan is different than what I've expected. But now I cannot find a decent way to get around this. 

Any ideas?

Thanks,
P

Tatu Saloranta

unread,
Aug 3, 2015, 2:18:56 PM8/3/15
to jackso...@googlegroups.com
The problem is that `readValueAs()` is bit heavy-weight, and does create a new deserialization context. We should probably add a warning to that effect: while sometimes convenient, it is not the suggested way of handling deserializer delegation.
Other than this, your approach makes sense to me and should work.

So: instead of delegating via `JsonParser`, you need to locate deserializers through `DeserializationContext`; either fully dynamically (if necessary), or in `createContextual()` method that gets called if deserializer implements `ContextualDeserializer`. Latter is more efficient as you can avoid further lookups, but does require that you know in advance all deserializers you will need.
You may want to implement `ContextualDeserializer` even if you do not pre-fetch delegate deserializers, to get reference to `BeanProperty` that represents property for which deserializer is used. This is needed if deserializer uses any property annotations for customizations.

DeserializationContext has couple of different `findXxxDeserializer()` methods; javadocs try to explain the differences, but essentially you will want to use one(s) that take `BeanProperty` (and not ones described as "root value" deserializers). Difference is not always evident in practice, but with polymorphic types, and deserializers that are annotation-customizable, difference is significant. Let me know if you end up having issues with this access.

-+ Tatu +-


--
You received this message because you are subscribed to the Google Groups "jackson-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jackson-user...@googlegroups.com.
To post to this group, send email to jackso...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages