Deserialize JSON for a class I dont own with custom getters - java

I am trying to deserialize an object of a class that I do not own. The class has attribute names such as id_, address_, name_, but its getters are getId() getAddress() getName() etc.
When I try to deserialize the JSON using Jackson, I get
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "id_", not marked as ignorable
It looks like this happens because Jackson's looking for getId_() instead of getId(). Since I do not own the underlying class, I cannot use Jackson's annotations to map attributes to custom json fields.
How can I deserialize with a custom mapping of object attributes to its getter methods?

You can try a custom deserializer.
check out: https://www.baeldung.com/jackson-deserialization
This way you can register a deserializer for the class.
However, you still have to edit it when the class changes.
One other thing you can try:
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
This will give the mapper full access to private members.

You can apply a MixIn for Jackson - that's how I solved my issue trying to serialize and deserialize JSON for an auto-generated AVRO class (Avro generated class issue with json conversion [kotlin])
Here is an example:
https://medium.com/#shankar.ganesh.1234/jackson-mixin-a-simple-guide-to-a-powerful-feature-d984341dc9e2

Related

POJO class should present while converting JSON to POJO?

I am trying to to convert JSON to POJO class. This JSON I am getting from third party REST API call and I want to convert it into POJO class. For this I am using jackson-databind jar and below is part of my code.
ObjectMapper mapper = new ObjectMapper();
Object modelObject; // object in which I want to convert my JSON object
mapper.writeValue(request.getShipmentDataJson(), modelObject);
Here for now instead of POJO class I declared modelObjcet variable of Object type and my question is do we need to create POJO class with required fields and getter setter methods before converting JSON to POJO?
If yes, then how should we create this POJO class from JSONSchema and when it get created?
Please explain me this concept. My understanding is we POJO should get create directly from JSONSchema but when and how that I don't know. And I think once POJO get created then I can use my above code to store JSON object to POJO.
You need an object with fields corresponding to incoming JSON (names and datatypes) - so jackson can populate and instantiate it. There are tools like this:
http://www.jsonschema2pojo.org/
to generate java code from JSON

Why can’t Jackson deserialize single field class with RequiredArgsConstructor?

If I have a class using Lombok:
#RequiredArgsConstructor
#Getter
class Example {
private final String id;
}
And try to deserialize it from
{
“id”: “test”
}
Jackson throws an exception that although at least one creator was provided, it could not deserialize.
If I then add another final String field to that class, and add that field to the JSON, it is deserialized with no complaints.
Does anyone know what’s going on here? Why are you unable to deserialize if you only have one field?
When only way to intialize object properties is through contructor, Jackson needs to be told that deserialization should happen using constructor via #JsonCreator annotation.
Also, all the property names should be provided via #JsonProperty annotation because Jackson needs to know the sequence of attributes passed in contructor to correctly map json values to Java object attributes.
So, if you are not using lombok contructor, then constructor will look like
#JsonCreator
public Example (#JsonProperty("id") String id) {
this.id = id;
}
If you don't want to manually write the contructor, go ahead with #tashkhisi's answer.
Also, I highly doubt following could happen. Could you update the question with code showing this?
If I then add another final String field to that class, and add that field to the JSON, it is deserialized with no complaints.

How to deserialize Json into java object if a property is not present in the java object(should ignore json element)using Jackson?

I am working on a project, where the Json contract may change overtime, If they had new property to the response Json, I might get a exception when deserializing into java object, How to ignore the new properties and only deserialize elements which are present in java Object, I am using Jackson 1.9.13, Does this version have feature which could ignore the Json element?
You can do this in 2 ways:
Add annotation to class:
#JsonIgnoreProperties(ignoreUnknown = true)
class <class_name>{
....
....
}
Configure ObjectMapper:
objectMapper.configure(Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);

Jackson parse json with unwraping root, but without ability to set #JsonRootName

The rest service responds with
<transaction><trxNumber>1243654</trxNumber><type>INVOICE</type></transaction>
or in JSON:
{"transaction":{"trxNumber":1243654,"type":"INVOICE"}}
There is no problems when I use:
mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true)
And as resulting class
#JsonRootName("transaction")
public class Transaction {
private String trxNumber;
private String type;
//getters and setters
}
But actually I should use the Transaction class from 3rd party jar, which is exact like above, but has no #JsonRootName("transaction") annotation.
So I end up with
Could not read JSON: Root name 'transaction' does not match expected ('Transaction') for type...
Is there any ways to force Jackson parse to Transaction class without adding any stuff to the Transaction class itself (as I get this file as part of a binary jar)?
I've tried custom PropertyNamingStrategy, but it seems has to do only with field and getter/setter names, but not class names.
Java7, Jackson 2.0.5.
Any suggestions? thanks.
You can do it with mixin feature. You can create simple interface/abstract class like this:
#JsonRootName("transaction")
interface TransactionMixIn {
}
Now, you have to configure ObjectMapper object:
ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
mapper.addMixInAnnotations(Transaction.class, TransactionMixIn.class);
And finally you can use it to deserialize JSON:
mapper.readValue(json, Transaction.class);
Second option - you can write custom deserializer for Transaction class.

Java Jersey use GET to return JSON that returns only some fields instead of all

Does naybody knows a way to use Jersey's GET method to return a JSON that returns only some fields of an entity instead of all?
Does anybody know a way to use Jersey's GET method to return a JSON that returns only some fields of an entity instead of all?
E.g. in the following class I want to receive (with POST) values for 'name' and for 'confidential', buy while returning (with GET) I only need 'name' value, not 'confidential'.
#Entity
#Table(name = "a")
#XmlRootElement
#JsonIgnoreProperties({"confifentialInfo"})
public class A extends B implements Serializable {
private String name;
#Basic(optional = false)
private String confifentialInfo;
// more fields, getters and setters
}
If you are using the JAXB approach, you can mark fields with #XmlTransient to omit them. If you are using POJO mapping or want to exclude fields only for some requests, you should construct the JSON with the low level JSON API.
If you are using Jackson, you can use the annotation #JsonIgnore for methods
Marker annotation similar to javax.xml.bind.annotation.XmlTransient
that indicates that the annotated method is to be ignored by
introspection-based serialization and deserialization functionality.
That is, it should not be consider a "getter", "setter" or "creator".
And #JsonIgnoreProperties for properties
Annotation that can be used to either suppress serialization of
properties (during serialization), or ignore processing of JSON
properties read (during deserialization).

Categories

Resources