Assigning a BeanPropertyWriter's serializer multiple times

93 views
Skip to first unread message

ross.g...@zestia.com

unread,
Oct 10, 2014, 11:19:34 AM10/10/14
to jackso...@googlegroups.com
Hi,

I'm using a SimpleBeanPropertyFilter to dynamically assign serializers for fields depending on query params passed into a JAX-RS endpoint. Everything is working fine apart from the fact I can't assign a serializer multiple times due to the following line in the assignSerializer method:

As there is a comment above this line suggesting the check might need to be disabled in the future am I safe to override the assignSerializer and allow serializers to be set multiple times? Is doing that likely to cause me any issues?

Thanks in advance,
Ross

Tatu Saloranta

unread,
Oct 10, 2014, 2:55:37 PM10/10/14
to jackso...@googlegroups.com
No, I would not recommend doing that. Serializers are meant to be as close to immutable as possible, and they are shared between concurrent threads. assignSerializer() is also not meant to be an extension point. So if you try to make that work, make sure you know challenges with concurrency and possible breaking future changes.

Since you need dynamically choose serializer to use, you may need to instead have custom serializer (or, perhaps, BeanPropertyWriter), and choose from different serializers there. You can do dynamic serializer lookup from there (or, earlier via ContextualSerializer, if possible types known statically).

-+ 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.

ross.g...@zestia.com

unread,
Oct 12, 2014, 6:55:05 AM10/12/14
to jackso...@googlegroups.com
Thanks Tatu.

If I use a custom serializer, what's the best way to dynamically lookup another serializer from the serialize method?

If I go the BeanPropertyWriter route, what method should I be doing the dynamic serializer lookup from?

Thanks again for the help,
Ross

Tatu Saloranta

unread,
Oct 12, 2014, 5:49:11 PM10/12/14
to jackso...@googlegroups.com
With custom serializer, two main ways: either get them looked up once, on ContextualSerializer.createContextual() (which is passed BeanProperty so you can see if there are any annotations), or, do it once per each value written by caling SerializerProvider.findRootSerializer (or whatever the name was).
Latter is more flexible, but adds lookup more overhead.

As to BeanPropertyWriter, if it gets handed SerializerProvider, that's the thing to use. If not, it is also possible to call JsonGenerator.writeObject(). This is not quite as good as calling SerializerProvider (it needs to create a new provider, and does not pass all type info), but probably works quite fine for most usage.

Hope this helps,

-+ Tatu +-


--

ross.g...@zestia.com

unread,
Oct 13, 2014, 5:29:24 AM10/13/14
to jackso...@googlegroups.com
I couldn't find the serializerProvider.findRootSerializer method, but serializerProvider.findPrimaryPropertySerializer seems to work fine instead.

My code now follows these steps:

1. JAX-RS endpoint is called and passed a couple of query params.
2. ObjectWriterInjector/ObjectWriterModifier are used to set the query param values as attributes on the ObjectWriter so they can be accessed within the serializers.
3. A custom serializer uses the query param values (retrieved from the ObjectWriter) to decide which serializer to use, falling back to the default returned from serializerProvider.findPrimaryPropertySerializer if necessary.

Does this seem like a better approach? Any obvious improvements I can make?

Thanks again,
Ross

Tatu Saloranta

unread,
Oct 13, 2014, 12:28:05 PM10/13/14
to jackso...@googlegroups.com
On Mon, Oct 13, 2014 at 9:29 AM, <ross.g...@zestia.com> wrote:
I couldn't find the serializerProvider.findRootSerializer method, but serializerProvider.findPrimaryPropertySerializer seems to work fine instead.


Ok right; naming betweeen serializer/deserializer side varies a bit. So that is probably the method to use.
 
My code now follows these steps:

1. JAX-RS endpoint is called and passed a couple of query params.
2. ObjectWriterInjector/ObjectWriterModifier are used to set the query param values as attributes on the ObjectWriter so they can be accessed within the serializers.
3. A custom serializer uses the query param values (retrieved from the ObjectWriter) to decide which serializer to use, falling back to the default returned from serializerProvider.findPrimaryPropertySerializer if necessary.

Does this seem like a better approach? Any obvious improvements I can make?

That sounds reasonable to me.

And if at all possible, an article or blog entry would be great, if you end up documenting your approach.
I think this is something that others would be interested in doing as well. Due to Jackson's design that focuses on high performance, many things are static, and trying to support more dynamic handling is often quite involved. So example code is useful to have, to know existing solutions.

-+ Tatu +-
 

Thanks again,
Ross
Message has been deleted

ross.g...@zestia.com

unread,
Oct 14, 2014, 6:13:54 AM10/14/14
to jackso...@googlegroups.com
Great, thanks - I'll try to get something written up once I've finished the implementation.

One final question (hopefully!)... is there a way to dynamically set a JsonView for a property? Depending on the query params passed to a JAX-RS endpoint I'm either outputting a partial or full representation of an embedded model. At the moment I'm using the customer serializer mentioned above to look up another custom serializer to output the partial representation - JsonViews feel like a better solution, I just can't work out how to dynamically set one for an embedded model depending on the query params passed to the endpoint.

Thinking a bit more about it, I guess I could use a custom annotation and a SimpleBeanPropertyFilter to achieve this?

Thanks again for the help, it's much appreciated.
Ross

ross.g...@zestia.com

unread,
Oct 14, 2014, 9:09:52 AM10/14/14
to jackso...@googlegroups.com
Ignore the SimpleBeanPropertyFilter suggestion, without knowing the level of nesting the current property is at it's not going to be helpful.

Tatu Saloranta

unread,
Oct 14, 2014, 1:41:56 PM10/14/14
to jackso...@googlegroups.com
Hmmh. Statically it is possible, I think, but for dynamic cases I think BeanPropertyFilter (via @JsonFilter) was designed to be more flexible.
However, it would seem like ability to control view dynamically should be possible, as per-property assignment (and global dynamic changing) require much of same functionality already.
Unfortunately I do not remember off-hand how to do it: but I think it should be possible (i.e. not one of "don't even try" things :) ).

-+ Tatu +-


On Tue, Oct 14, 2014 at 10:08 AM, <ross.g...@zestia.com> wrote:
Great, thanks - I'll try to get something written up once I've finished the implementation.

One final question (hopefully!)... is there a way to dynamically set a JsonView for a property? Depending on the query params passed to a JAX-RS endpoint I'm either outputting a partial or full representation of an embedded model. At the moment I'm using the customer serializer mentioned above to look up another custom serializer to output the partial representation - JsonViews feel like a better solution, I just can't work out how to dynamically set one for an embedded model depending on the query params passed to the endpoint.

Thanks again for the help, it's much appreciated.
Ross
Reply all
Reply to author
Forward
0 new messages