Spring Data Elasticsearch 4 - Override Object Mapper? - java

Previously in version 3 of Spring Data Elasticsearch, the Jackson mapper was used by default, but could be overridden to use the Metamodel object mapper, as documented here:
https://docs.spring.io/spring-data/elasticsearch/docs/3.2.0.RC1/reference/html/#elasticsearch.mapping.meta-model
I understand the Jackson mapper has been removed in version 4 and replaced with the Metamodel object mapper, as documented here:
https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#elasticsearch.mapping
But it appears the ability to override the object mapper was removed as well. Is there indeed no way to configure the Elasticsearch global object mapper to use Jackson (or any other mapper) again? It seems like a shame to lose the flexibility that option provided.

No. The MappingConverter is not only used and needed for converting an entity to and from JSON, but also for converting and mapping fieldnames, dateformats and other stuff for example when CriteriaQuerys are created or when search resukts like highlights are processed. There are man places in Spring Data Elasticsearch where the mapping information for an entity is needed and Jackson cannot be used there.
So in versions before 4.0 it was necessary to customize Jackson with jackson-annotations on the entity and the other stuff with different annotations, this has been consolidated.
What functionality do you need that the MappingConverter (implementation of the meta model mapper) does not offer in combination with custom converters?
Edit 05.12.2020:
valid point from the comments: It should be possible to define a FieldNamingStrategy for an entity. I created an issue for that.

Related

Jackson's #JsonAppend with default value

guys! I am developing a web application and I decided to use Jackson as my JSON processing framework.
In request data that I am willing to send; let's say the POJO looks like this:
data class JSONEnvelope(
#JsonProperty("obj1")
val obj1: Obj1,
#JsonProperty("obj2")
val obj2: Obj2)
which get serialized like this:
{
"obj1":{...},
"obj2":{...}
}
but I need to add some metadata to that object, let's say fields meta1 and meta. I thought that #JsonAppend would solve my problem, but I am using Jackson together with Jersey, so I am not serializing objects manually, so I cannot use writer.withAttribute("...", ...).
I am aware of this thread, but there is no answer that kinda satisfy my needs, because I think, that writing a custom serializer is a bit overkill for this, moreover if I do not have a mechanism to "serialize the rest of the original object". I'd be glad for any ideas
The solution in the answer you cited, which adds a mixIn to a the ObjectMapper then uses the ObjectWriter to configure it, is a good solution.
For Jersey, which calls ObjectMapper.writerFor and therefore prevents you from calling withAttribute in order to configure the ObjectWriter, one alternative is to add the attribute to the ObjectWriter before returning it from writerFor. I suggest subclassing ObjectMapper and overriding the various writerFor methods, adding the necessary attribute at that point. You can then get Jersey to use that ObjectMapper by registering it as a JAX-RS Provider: see the various annotations in javax.ws.rs to get started on this. This answer gives an example of what to do.

How is javax.ws.rs.client.Entity serializing objects to json?

What serializer is Entity.json(T entity) using to serialize/deserialize objects? Is it somehow possible to use a custom serializer?
In my case the serialization is wrong because my object contains fields with the Guava Optional data type and absent values are returned as {"present":false} instead of null.
The JSON serializer isn't specified by JAX-RS, it depends on your configuration. For example, Jersey JAX-RS allows several (https://jersey.java.net/documentation/latest/media.html), including
MOXy
Java API for JSON Processing (JSON-P)
Jackson
Jettison
But a better solution is not to use Optional (either Guava or Java 8) for fields. See http://blog.joda.org/2014/11/optional-in-java-se-8.html
My only fear is that Optional will be overused. Please focus on using
it as a return type (from methods that perform some useful piece of
functionality) Please don't use it as the field of a Java-Bean.
Not directly solving your problem. I suggest you use Googles Gson as a parser. It is very flexible and configurable.
Tutorial
It also skips blank fields so the json size is not too large.

Deep JSON Serialization of JPA Entities

Using jersey-json POJO serialization feature on a jersey service function to return a JPA entity or a List<?> of that entity, how can I "tell" the serializer to dig deeper when serializing?
In other words, how do I tell the POJO Serializer to do a "Deep Serialization" (or specify the depth of each property) which returns a more detailed JSON with deeper data of the JPA object including it's mappings and relationships with other objects, those annotated with #ManyToOne and #OneToMany?
Without having to use that kind of solution: https://stackoverflow.com/a/10615608/230637
(My problem with the linked solution is the necessity to declare a bloated copy-constructor).
Thanks.

With Jackson is it possible to just ignore all cyclic relationship without having to add annotation?

Jackson 2.0 has pretty good support for cyclic reference, however, it seems that all require to annotate the POJO classes. What if I cannot edit the java classes I want to serialize to json, but want to just ignore cyclic reference like the json lib jsonConfig.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT) which basically ignore cyclic reference when one occurs.
No. Jackson does not do full cycle detection; identity checks are only done when annotation indicates that they are needed.

JAXB is good until I need to do something complex. What are the alternatives?

JAXB works well until I need to do something like serialize beans for which I cannot modify the source. If the bean doesn't have a default constructor or if it refers to objects I want to mark transient then I'm stuck writing a separate bean which I can annotate and then manually copy the information over from the other bean.
For instance, I wanted to serialize exception objects, but found that the only way to do that was use a hack that required using com.sun.* classes.
So, what alternatives are there? What's the next most popular xml serializing api? It would be nice to be able to do things like:
Choose at serialization time whether to include certain fields in the result. (marking things transient when running the serializer).
Handle loops in the object graph by using references or something other than just dying.
Perhaps annotate an object so that in version 1 it serializes things in one way and in version 2 it serializes them in another. Then when serializing I just choose which version of the object ot serialize.
Have a way to generate XSDs from annotations on an object.
Basically I just want more flexibility than I currently have with JAXB.
Well the standard answer for wanting a uber configurable serialisation framework is xstream.
JAXB is a spec, so you can pick from different implementations. EclipseLink JAXB (MOXy) has extensions for what you are asking:
Externalized Metadata
Useful when dealing with classes for which you cannot annotate the source or to apply multiple mappings to an object model.
http://bdoughan.blogspot.com/2010/12/extending-jaxb-representing-annotations.html
http://wiki.eclipse.org/EclipseLink/Examples/MOXy/EclipseLink-OXM.XML
XPath Based Mapping
For true meet-in-the-middle OXM mapping:
http://bdoughan.blogspot.com/2010/09/xpath-based-mapping-geocode-example.html
http://bdoughan.blogspot.com/2011/03/map-to-element-based-on-attribute-value.html
http://bdoughan.blogspot.com/2010/07/xpath-based-mapping.html
http://wiki.eclipse.org/EclipseLink/Examples/MOXy/GettingStarted/MOXyExtensions
JPA Compatibility
Including support for bi-directional relationships.
http://bdoughan.blogspot.com/2010/07/jpa-entities-to-xml-bidirectional.html
http://wiki.eclipse.org/EclipseLink/Examples/MOXy/JPA
Also look at JIBX. It's a good xml<->object mapper. My experience is though that if your objects have a somewhat funky relationships it's often easier to create a wrapper object that hides that complexity and then map that object with JIBX.
XStream is a popular XML serialisation library that claims to be able to serialize just about anyting, regardless of constructors or other problems (even deserialize final fields). Give it a try.
Requires no modifications to objects. Serializes internal fields, including private and final. Supports non-public and inner classes. Classes are not required to have default constructor.

Categories