I have a JPA transient property in an entity which has a calculated value based on multiple fields in the POJO. All these calculations are done in the GETTER of that property.
But, Jackson doesnt seem to be using the GETTER when creating the JSON for that POJO.
How do I configure Jackson to use getter for the property?
My POJO looks something like below
#Entity
public class ProductSummaryEntity implements Serializable {
#Basic
private String field1;
// GETTER and SETTER for Field1
#Basic
private String field2;
// GETTER and SETTER for Field2
#Transient
private String field3;
public String getField3(){
setField3(field1 + field2);
return this.field3;
}
public void setField3(String temp){
this.field3=temp;
}
}
This link to a blog by #sghill has been posted on SO before and shows you how to customize the serialization process: https://www.sghill.net/how-do-i-write-a-jackson-json-serializer-deserializer.html
Essentially, annotate your POJO with #JsonSerialize(using = CustomSerializer.class) and then implement a class CustomSerializer that's extending from JsonSerializer. In your implementation you can build the JSON however you like and calculate values on the fly or call your getters.
No, I don't think you can serialize transient field unless there is something latest is there.
Related
I'm running into an issue with my pojo created using lombok with jsonproperty annotation. It doesn't respect the json annotation. And, when i create an object using the lombok builder it uses the field names on the object instead of json property.
Could someone help see what am I missing here. I just started using lombok so im hoping something straightforward. I'm running the code on Intellij
#Data
#Builder
public class pojo {
#JsonProperty("grant_type")
private final String grantType = "xyz";
#JsonProperty("client_id")
private String clientId;
}
It's default behavior of #Builder.
If we want the builder with setClientId, We can add setterPrefix = "set" into #Builder.
#Data
#Builder(setterPrefix = "set")
public class pojo {
#JsonProperty("grant_type")
private final String grantType = "xyz";
#JsonProperty("client_id")
private String clientId;
}
#Data would generate a pair of setter/getter. But setter is a member method of pojo, not pojoBuilder's.
More details of Builder is here.
So, I have this class, using #EmbeddedId and #JsonUnwrapped annotations
#Entity
class Order {
#EmbeddedId #JsonUnwrapped
private OrderPK pk;
private String field1;
private String field2;
//...getters, setters
}
And this is the primary key class
#Embeddable
class OrderPK implements Serializable {
private String orderNumber;
private String company;
//...getters, setters
}
I wanted to make Spring Data REST sorting treat the fields in the PK class as top-level instead of nested. Basically, I want to use this one: .../orders?sort=orderNumber,desc, instead of .../orders?sort=pk.orderNumber,desc. I couldn't find any way to do this in the documentations.
You can no longer achieve your goal, if you are using the #EmbeddedId option to implement your composite key. The reason is that the attributes under the hood of EmbeddedId class cannot be taken out as flat parameters.
Note that #JsonUnwrapped is not intended to perform that task.
You can use the following option instead of #EmbeddedId to achieve your goal.
Use #IdClass. Follow this example.
Is there a class level annotation for jackson's #JsonProperty ? Without knowing what field names are in the class, I can be able to annotate the class with a annotation and it will map it for me automatically?
Currently I have to annotate each field with a JsonProperty, is there something I can do at the class level that servers the same purpose?
public class myEntity() {
#JsonProperty("banner")
private String banner;
#JsonProperty("menu")
private String menu;
}
Class level annotation
#JsonRootName("Response")
public class SuperResponse {
...
}
Result:
<Response>
...
</Response>
#JsonProperty is not class level annotation, and you don't need to mark your class with any annotation. If you provide your class name as an argument to parser it will know how to map it according to your getter methods. It is as if every getter method has been marked with #JsonProperty without any argument
#JsonRootName(value = "user")
public class User {
public int id;
public String name;
}
I am new to Spring-MVC.
I am sending data to my view as JSON, and there I am deserializing it to a string, but I want to pass only selected fields, I don't want all fields to send there but how to ignore selected fields I don't know.
My class POJO code :
public class account{
private Integer userId;
private String userName;
private String emailId;
//getter - setter
}
In some activity I don't want some fields so I want to avoid that fields so any idea on this confusing situation ?
Add the annotation #JsonIgnoreProperties("fieldname") to your POJO.
or you can use #JsonIgnore also before field name that you want to ignore while deserializing JSON.
example :
#JsonIgnore
#JsonProperty(value = "user_password")
public java.lang.String getUserPassword()
{
return userPassword;
}
Here Is my Answer for Similar Question.
Is it possible to store something like the following using only one table? Right now, what hibernate will do is create two tables, one for Families and one for people. I would like for the familymembers object to be serialized into the column in the database.
#Entity(name = "family")
class Family{
private final List<Person> familyMembers;
}
class Person{
String firstName, lastName;
int age;
}
This is an horrible design and I'm really not recommending it (you should just create another table) but it is possible.
First, you'll need to use a byte[] attribute to hold a serialized version of the list of persons that will be stored in a BLOB in the database. So annotate it's getter with #Lob (I would make the getter and setter private to not expose them). Then, expose "fake" getter and setter to return or set a List<Person> from the byte[]. I'm using SerializationUtils from Commons Lang in the sample below (provide you own helper class if you don't want to import this library) to serialize/deserialize on the fly to/from the byte[]. Don't forget to mark the "fake" getter with #Transcient or Hibernate will try to create a field (and fail because it won't be able to determine the type for a List).
#Entity(name = "family")
class Family implements Serializable {
// ...
private byte[] familyMembersAsByteArray;
public Family() {}
#Lob
#Column(name = "members", length = Integer.MAX_VALUE - 1)
private byte[] getFamilyMembersAsByteArray() { // not exposed
return familyMembersAsByteArray;
}
private void setFamilyMembersAsByteArray((byte[] familyMembersAsByteArray() { // not exposed
this.familyMembersAsByteArray = familyMembersAsByteArray;
}
#Transient
public List<Person> getFamilyMembers() {
return (List<Person>) SerializationUtils.deserialize(familyMembersAsByteArray);
}
public void setParticipants(List familyMembers) {
this.familyMembersAsByteArray = SerializationUtils.serialize((Serializable) familyMembers);
}
}
Don't forget to make the Person class Serializable and to add a real serialVersionUID (I'm just showing a default here):
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
// ...
private String firstName, lastName;
private int age;
}
But, let me insist, this is an horrible design and it will be very fragile (changing Person might require to "migrate" the content of the BLOB to avoid deserialization issues and this will become painful. You should really reconsider this idea and use another table for the Person instead (or I don't get why you use a database).
#Type(type = "serializable")
private List<Person> familyMembers;
if you can't use hibernate annotations try this:
#Lob
private Serializable familyMembers;
public List<Person> getFamilyMembers(){
return (List) familyMembers;
}
public void setFamilyMembers(List<Person> family){
familyMembers = family;
}
Annotate the property with #Column and define the type to be ArrayList, not just List. And make Person implement Serializable.
But you should do this only if your motives are very clear, because this is the correct solution in some very rare cases. As Pascal noted, if you ever have to change Person you'll have headaches.
You can create pseudoproperty (getter and setter) which accepts/returns the serialized form, and annotate the familyMembers with #Transient. This would also need to annotate the getters, not fields, for all other properties.