Currently I'm using lift-json to parse json into objects. This is the signature I generally use
net.liftweb.json.parse(json).extract[MyClass]
This is working fine. However, I'm looking to do a little more. Lets say My class has an object of type List[SomeTrait] where SomeTrait is a trait. And I have two different implementations of that trait with the different constructor signatures, but obviously implementing the same methods differently.
Is there a way in either the JSON or the code that will detect which implementation it should use? Such that, the code parsing the json can remain the same but I can continue to add new implementations of SomeTrait
There's no easy way to do that in Lift, as far as I know. You still need to have some attribute to be able to provide the type information about the JSON object itself, so the deserializer will be able to pick up the proper instance.
I'd use Jackson JsonTypeInfo annotation in order to mark subclasses and then use it's ObjectMapper to do the job.
Look https://github.com/FasterXML/jackson-annotations#handling-polymorphic-types for more details.
Related
I'm trying to implement a logic that serializes and de-serializes a very complex legacy object. The object contains other complex objects inside of it that are spread through various other projects. There are even some JAXB1 objects that are generated from an xsd schemas and are part of the chain.
Right now there is already a working version that uses XStream and this worked for years. But since Java 17 there are issues because of the new restriction for using reflection on private fields from different modules. Exceptions like this started to appear ->
Module {A} does not 'opens {package}' to {B}". One of the things that bothers me is that all of these packages are from some third party libs and I even can't find any objects from them in the model chain.
So I started implementing a new serialization based on the Jackson databind API but right now I'm wondering is it going to solve the issues at all? Does Jackson also use reflection in case to serialize and de-serialize? What is the best way to configure the ObjectMapper and what should I change in the objects that I need to work with in case to make the reflection usage as low as possible?
Right now I've configure the ObjectMapper as:
objectMapper.disable(MapperFeature.AUTO_DETECT_CREATORS,
MapperFeature.AUTO_DETECT_FIELDS,
MapperFeature.AUTO_DETECT_GETTERS,
MapperFeature.AUTO_DETECT_IS_GETTERS);
objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
and I'm annotating all fields that should be serialized with #JsonProperty but I'm not sure that this is going to help. Okay, I assume I must have getters and setters, but should I also annotate them? Does the annotation has something to do with the reflection usage at all?
A JsonObject can be transformed into it's corresponding class instance via:
Pojo pojo = JsonbBuilder.create().fromJson(jsonObject.toString(), Pojo.class)
However, it seems to be inefficient to use jsonObject.toString() as a String is an other intermediate representation, that contains the same information. I need to transform the jsonObject before the object binding. So is there a more efficient way to achieve the binding from a JsonObject?
(Note I want to implement with Java EE 8 standards, so Gson and Jackson is not an option, but may be concepts of it). There is currently not answer in the Yasson group so hopefully, someone finds this. Michael Schnell also proposed a JsonStructure binding, but there is no solution yet too.
It is not possible with the JSON-B 1.0 standard to convert JSON-P object <--> POJO. However, enough people have asked for it that it's certainly something we will consider for the next version of JSON-B.
In the meantime, converting to String or using a custom adapter is your best option.
If you are concerned about performance with JSON-B, the #1 thing you can do to improve JSON-B performance is cache the instance of Jsonb, namely, don't call JsonbBuilder.create() each time you need to call to/fromJson, because all of the annotation scanning and class parsing happens upon creation of the Jsonb instance.
Update (June 2019):
Although there is still no JSON-B standard way of doing this, the JSON-B reference implementation, Eclipse Yasson, has added support for this on the org.eclipse.yasson.YassonJsonb interface in this PR. Hopefully this function will get included in the next version of the JSON-B spec.
ExcludeStrategy in Gson allows you to filter fields based on reference type. But due to polymorphism, we can have an object that contains much more fields. Which basically means ExcludeStrategy is actually useless in this case. I think this was quite a bad design in Gson.
The issue is that by getting the field, you can find out what class/interface that field was declared in, but can't find out what is the actual instance that is currently processed by Gson. So you can't use ExcludeStrategy other than for pretty basic models, not for hierarchies.
Is there a way to tell Gson what fields to log and which to skip, without using annotations, at runtime?
Maybe something like SimpleBeanPropertyFilter in Jackson framework?
There isn't anything for this. I've opened an issue with a suggestion of how to get this outcome, but so far no updates:
https://github.com/google/gson/issues/1272
Follow that issue for an update. I'll also update this answer whenever there's any progress.
Looking for some help to serialize a deep nested java objects to Json. The constraint is that I cannot add any annotations or change the current Java code. Looking for a powerful Json library which has configuration options to convert Java to Json without altering the Java Object themselves. Following would be some of the options that might be required
Specify include/exclude fields/methods. Should be able to specify this at nested levels. A is composed of B and B is composed of C. Should have ability to specify include/exclude at C.
Include/Exclude Objects at nested levels.
Rename fields from java properties while converting to Json (at nested level objects too)
Manager circular dependencies.
Was looking at Jackson and Gson for this requirements. While there are tons of options using annotations to specify serialization configs while writing new Java Pojo's, I am looking at options where I need to specify serialization properties without changing the current Java code. Jackson and Gson do seem to have options for these, but not documented in depth.
Which library is easier to configure for the above requirements? Any other powerful library other than Jackson/Gson? Any pointers to this will be of great help.
Thanks much for your time.
As to Jackson, you might consider using so-called mix-in annotations (see f.ex http://www.studytrails.com/java/json/java-jackson-mix-in-annotation.jsp) which allow you to specify mix-ins to use, without adding them directly in the legacy classes.
This would let you use annotation-based configuration, but leave actual classes untouched.
But given all of your requirements, it may perhaps be better to just use Tree Model of Jackson or GSON (get JsonNode or such), and manually handle conversions to your liking.
You may then be able to convert tree value into POJO; Jackson, for example, has method(s) for doing this (ObjectMapper.treeToValue(), .valueToTree(), .convertValue()) which allow conversions of structurally compatible representations.
Is there a way to perform serialization/deserialization in Jackson of polymorphic classes w/out using annotations or specialized bean fields? I have to support class hierarchies that I cannot modify and don't wish to use annotations.
I'd like to be able to designate a synthetic name, which would not be in the classes that I am serializing/deserializing, that would be inserted into the JSON representation and used to identify the type.
If mix-ins are not to your liking, there isn't anything pre-defined to pass, but you can relatively easily achieve this by sub-classing JacksonAnnotationIntrospector and configure mapper with it.
In your implementation you can override all aspects of annotation access: in your case it's probably enough to override findTypeResolver() (and if you want per-property overrides, 'findPropertyTypeResolver()').
The method can then use whatever mechanism you want to construct TypeResolverBuilder (most likely StdTypeResolverBuilder) that contains same information as what would usually come from #JsonTypeInfo annotation.
For anyone looking for polymorphic json unmarshaling problems, you should check out this post, which gives great examples & workarounds for JSON serialization / deserialization caveats.
And if mixins (step 5 at the above mentioned post) is not what you're looking for than go for the accepted answer by StaxMan.