Can Jackson remove the #JsonFilter restriction - java

My code use a default ObjectMapper without filters defined, but the target class with a #JsonFilter annotation. My expectation is to Jackson will ignore the annotation and do a normal thing.
And in another case, if I want to use the filter and I also give the filter defined, why must add #JsonFilter to the class otherwise jackson will work as no filter.
#JsonFilter looks a redundant thing. We already defined the filters. The real issue is the problem described at beginning. We can't modify the class with annotation, we just serialize the class with normal behavior.
There's way to create a dummy filter and set setFailOnUnknownId(false). But this looks not so general.

Related

Jackson handle 3rd party java type

I am providing the ability to deserialize a list of entities returned from JPA, however the list type returned from JPA is DelegatingResultList which has no default constructor.
The implementation uses proxy beans with AOP where I intercept interfaces that extend a set of interfaces to provide basic queries.
I can easily fix this by checking in my aspect if the object type is DelegatingResultList and then copy to an ArrayList, but I don't want to have to do this for every single aspect that I'm covering.
I am using the default typing to set as a property like so:
objectMapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY);
The json in the serialized format with my value wrapper looks like this:
{"#class":"my.wrapper.ValueWrapper",
"response": ["org.apache.openjpa.kernel.DelegatingResultList",
[{"#class":"my.entity.TaxInfoEntity","taxType":"01","taxVal":"0.07"}, ..."]]"}
I have read about using mixins and custom deserializers, but everything I've tried doesn't seem to work.
I have tried using a Mixin, but I have no reference to the ResultList property as it's not saved in the json. Not to mention it doesn't even kick in when it's trying to deserialize.
I have tried using a custom deserializer but again, this never kicks in when deserializing. Would I be correct in assuming the mixin and custom deserializer only kick in if you try to deserialize passing the class as the type?
This of course would be read only as it's a cached value. So my intention is to convert to an Arraylist instead. How would I achieve this using Jackson?

How to use Jackson PropertyNamingStrategy with Immutables library

I am using https://immutables.github.io/ library with Jackson.
I want my class to be Jackson-serializable. I would like to use custom PropertyNamingStrategy (configured for com.fasterxml.jackson.databind.ObjectMapper using mapper.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
Unfortunately Immutables library puts #JsonProperty("propertyName") at every field in generated code. That overrides PropertyNamingStrategy defined at mapper level (or at class level, using #com.fasterxml.jackson.databind.annotation.JsonNaming annotation).
Is it possible to make Immutables library stop putting property name for every field (using org.immutables.value.Value.Style or similar means)?
I have come with workaround, putting #JsonProperty (without value) at every property, but I am not satisfied with this.
Style property forceJacksonPropertyNames=false does not force property names to specific strings. It works with naming strategies configured at class level and at mapper level.
Introduction to styles is available here: http://immutables.github.io/style.html
You can read some background information about this setting in issues: https://github.com/immutables/immutables/issues/431 https://github.com/immutables/immutables/issues/353

jackson - ignoring case in snake case keys

I have a requirement to receive JSON with keys that contain underscore and even ignore the case in words. For e.g. Device_control_API, device_control_API, Device_Control_API, device_control_aPI etc all should map to same property.
Now I know that I can create multiple setter methods using #JsonSetter with all combinations possible, but I don't think that will be good.
I have seen other questions which suggest using mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true)
for ObjectMapper object to ignore case, but I can't do that because I am using spring-boot and want my REST API to get payload in the form POJO object.
Is there any annotation or some way to do so
Please help !!!
I dont think you can use the MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES as annotation. Got the following information from here
Jackson on/off features: MapperFeature
Jackson defines a set of per-mapper configuration, which can ONLY be
defined before using ObjectMapper -- meaning that these settings can
not be changed on-the-fly, on per-request basis. They configure
fundamental POJO introspection details, and resulting built objects
(serializers, deserializers, related) are heavily cached. If you need
differing settings for these, you have to use separate ObjectMapper
instances.
And the MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES is one of the configuration.
But maybe a custom deserialization class could help you. There are many tutorials and questions on Stackoverflow.
I found some:
Jackson: using #JsonSerialize (or #JsonDeserialize) annotation to register a custom serializer (or deserializer)
Right way to write JSON deserializer in Spring or extend it
There is also this property:
spring.jackson.mapper.accept_case_insensitive_properties=true

Jackson - Overriding #JsonIgnore in MixIn

I have a property that that is #JsonIgnored on a class. And I wanted to make it available on some particular flow. I know that on a subclass, one can just use #JsonIgnored(false), and it overrides the base class annotation.
However, this does not seem to work via the MixIn, what works though is adding the #JsonProperty in the MixIn Interface/Abstract class. However, I am not too sure if this is safe and is consistent behavior.
Thanks.

How to extend Jackson property discovery in a "catch-all-types" way?

Following my previous question about serialization only, I'd like to go further and support JsonFormatVisitor.
I have the same requirements, that is:
I have objects of several types (interfaces).
I don't know the type of theses objets in advance.
I can't add annotations on theses types.
I can introspect all theses objets to get their state data.
Now that serialization works, I need to generate JsonSchema and hence do something like that:
SchemaFactoryWrapper visitor = WHAT?
mapper.acceptJsonFormatVisitor( mapper.constructType( Foo.class ), visitor );
JsonSchema jsonSchema = visitor.finalSchema();
String schemaString = mapper.writeValueAsString( jsonSchema );
I've implemented a SchemaFactoryWrapper that gets its expectAnyFormat called but I don't know what to do inside it. Looks like there's no schema for "any" objects.
Maybe I can hook elsewhere in jackson? Maybe it is possible to extends the whole Bean/Property introspection mechanism to support a completely different model (ie. not beans)?
I'm a bit lost, please help me find the treasure room :)
I can try to suggest some approaches that may be helpful.
First, even if you can not annotate classes directly, "mix-in annotations" can help -- this does assume static knowledge, however
Second, since schema-generation uses type detection used for serialization, you may want to register custom serializers; but this does not necessarily mean having to hand-write all. The most flexible way to register custom serializers is via Module interface (mapper.registerModule(new MyModule()); Modules can register Serializers instance which gets called when trying to locate a JsonSerializer for a type for the first time (after this, instance is cached to be re-used for other properties of same type).
This is where you could configure and return your custom JsonSerializer; but it might only need to handle schema-related callback(s) (one(s) called by schema generator).
It is also possible to extend/modify property discovery mechanism; whether this is easier depends. But the thing to look for is registering BeanSerializerModifier via Module.
It gets called during construction of BeanSerializer (general POJO serializer used unless something more specific is registered), and with it you can add/modify properties; or just replace resulting serializer altogether (and also then allows chaining of custom serializer with default one, if needed).

Categories

Resources