I have an Entity "Task" that has an Id property, but I don't need the field to be returned in the JSON file.
#Entity
public class Task {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#JsonIgnore
private Integer Id;
#JsonProperty("task")
private String taskName;
private String status;
//getter and setter
}
However, the annotation #JsonIgnore doesn't filter the field when I make the get request, see below:
{
"status": "started",
"timestamps": {
"submitted": "2018-12-31T00:34:20.718+0000",
"started": "2018-12-31T00:34:20.718+0000",
"completed": "2018-12-31T00:34:20.718+0000"
},
"id": 40001,
"task": "q094hiu3o"
}
What is the proper way to prevent "Id" to be displayed?
So here is the problem jackson had issue with hibernate issue, try using #jsonIgnoreProperties on class level
#JsonIgnoreProperties(ignoreUnknown = true,
value = {"id"})
You can try to add the #JsonIgnore only on your getter:
#JsonIgnore
public Integer getId() {
return id;
}
Also I would suggest to add the #JsonProperty annotation on your id field, if it is available in the Jackson version you are using:
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#JsonProperty(access = Access.WRITE_ONLY)
private Integer id;
WRITE_ONLY
Access setting that means that the property may only be written (set) for deserialization, but will not be read (get) on serialization, that is, the value of the property is not included in serialization.
Jackson documentation here
Related
I have two web services: "Proprietario" and "Veiculo", the "Proprietario" contains a list of "Veiculo" and "Veiculo" contains a "Proprietario".
The problem is that when I make a request calling the findAll method of "Proprietario", when trying to serialize, Jackson goes into infinite loop throwing exception. The same happens when I try to call the findAll method of "Veiculo".
I would like it when I call you to call the findAll of the "Veiculo", bring along the "Proprietario", but do not bring the "Veiculo" list inside the "Proprietario". The opposite of when I call the findAll method of "Proprietario", I'd like to bring the "Veiculo" list, but do not bring the "Proprietario" into the "Veiculo".
I tried to use some Jackson annotations, but none solves the conflict on both sides.
#Getter
#Setter
#Entity
#EqualsAndHashCode(of = "id")
public class Veiculo {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
#Column(length = 10)
private String placa;
#Column(nullable = false)
private Integer ano;
#ManyToOne
#JoinColumn
private Proprietario proprietario;
}
#Getter
#Setter
#Entity
#EqualsAndHashCode(of = "id")
public class Veiculo {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
#Column(length = 10)
private String placa;
#Column(nullable = false)
private Integer ano;
#ManyToOne
#JoinColumn
private Proprietario proprietario;
}
Try using these two annotations
#JsonManagedReference and #JsonBackReference
see http://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion
For a given #Entity with a #ManyToOne relation I want to suppress the mapping of the associated type. The JSON representation should contain the forein key (#JoinColumn) instead.
#Entity
public class OrderPosition implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#ManyToOne
#JoinColumn(name = "order_id", referencedColumnName = "id")
//#Json???
private Order order;
// ...
}
orderPosition = new OrderPosition()
// ...
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(orderPosition);
assertThat(json).contains("\"order_id\":");
How could I archieve it?
You can use the following solution:
#JsonProperty("order")
public Integer getOrderId() {
return this.order.getId();
}
The JsonProperty annotation causes to use this getter for serialization the "order" attribute. So you can only return the id for your use case. I would recommand to use a nice name of getter (not getOrder() ...).
Probably you could just add a #JsonIgnore to the order field and another field for the orderId.
I get this exception when Jackson tries to parse my data to Json:
org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: failed to lazily initialize a collection of role: packagename.Thing.Stuffs, could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->packagename.Stuff[“thing"]->packagename.Thing[“stuffs"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: packagename.Thing.Stuffs, could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->packagename.Stuff[“thing"]->packagename.Thing[“stuffs"])
I have the following entities(names have been replaced with Stuff and Thing):
Stuff:
#Entity
#Table(name = "stuff")
#SQLDelete(sql = "UPDATE stuff SET deleted = 1 WHERE id = ?")
#Where(clause = "deleted = 0")
public class Stuff implements Serializable {
private Long id;
private Thing thing;
private String stuffName;
#Id
#Column(name = "id", unique = true, nullable = false)
#GeneratedValue
public Long getId() {
return this.id;
}
#ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, optional = false)
#JoinColumn(name = "thing_id", nullable = false)
public Thing getThing() {
return thing;
}
#Transient
public String getStuffName() {
return stuffName;
}
// Setters and constructor(s) omitted
}
Thing:
#Entity
#Table(name = "thing")
public class Thing implements Serializable {
private Long id;
private String name;
private List<Stuff> stuffs;
#Id
#Column(name = "id", unique = true, nullable = false)
#GeneratedValue
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
#Column(name = "name", unique = false, nullable = false, length = 45)
public String getName() {
return this.name;
}
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "thing_id")
#JsonIgnore
public List<Stuffs> getStuffs() {
return stuffs;
}
// Setters and constructor(s) omitted
}
I have been googling for this type of error. It seems that this is happening when the json-parser is trying to parse objects that aren't loaded due to lazy-load. Lazy load seems to be on by default. I'd like to avoid setting everything to eager so I put #JsonIgnore instead. Changes nothing for me. Help would be greatly appreciated, this is driving me nuts.
EDIT:
Adding #JsonIgnore and #Eager in both classes gives me another problem. An exception that is looking like this:
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver.doResolveException Handling of [org.springframework.http.converter.HttpMessageNotWritableException] resulted in Exception java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
Searching for that on stackoverflow gives me this: Hibernate and Jackson (java.lang.IllegalStateException: Cannot call sendError() after the response has been committed)
The link is basically saying that I should add #JsonIgnore, and I have already done that.
From comments you said that you are using Jackson 1.9.10, which will allow you to use the new syntax of #JsonProperty annotation by adding READ_ONLY and WRITE_ONLY property for access type.
So you can use :
#JsonProperty(access = Access.WRITE_ONLY)
With your field definition.
For further details you can check Only using #JsonIgnore during serialization, but not deserialization discussion.
Note:
With older cersions you could just use #JsonIgnore on class member getter and #JsonProperty on its setter.
Maybe your problem caused by wrong mapping, you shouldn't use #JoinColumn for #OneToMany relation in Thing entity, you need to add mappedBy = "thing" as parameter to specify relationship correctly.
Please, explain for what purpose #Transient was placed on getter and setter methods at the same time as #Column was placed on field.
The field is stored to DB as we need.
#Entity
#Table(name = "person")
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private long id;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#Column(name = "name")
private String name;
#Transient
public long getName() {
return name;
}
#Transient
public void setName(String name) {
this.name = name;
}
}
this is actually a tricky situation. #transient annotation and transient keyword doesn't provide same functionality. using transient keyword will not serialize your data. but using #transient annotation will serialize the data but will not be persisted in the database, since you have marked the field with #column annotation that field will be persisted in the database because #Column allows you to specify the name of the column in the database to which the attribute is to be persisted.
In the code as you have it, they have no effect, since the #Id on a field causes the default access to be field, thus ignoring any method annotations. If property access was the default (either by #Id on the getter or #Access(PROPERTY) on the class), the #Transient annotations would cause JPA to ignore the accessors, presumably so that the field mapping could be picked up. However, in that case, the field should be annotated with #Access(FIELD).
I'd say the #Transient annotations are leftovers from a time when the entity had default property access.
I suspect its ignored since the column is marked already and as you say it is being updated as required. Enabling logging would confirm this as it would generate a warning
You could do a test creating a new test field and marking the getter/setter as Transient
I use Java Persistence, and I want a web method to return a 'portion' of an Entity class. For example, I have a Customer class that represents a record in Customer table with many fields, but I want to return just few of them. Is it possible to use mapping to do that? Or the only way is to create a new class (maybe a superclass for Customer) that has only fields I want to return? I tried binding, but it didn't work (apparently I did it in a wrong way):
#Entity
#Table(name = "Customer", catalog = "test", schema = "")
#XmlType(name = "Customer")
public class Customer implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
#XmlElement
private Integer accountId;
#Basic(optional = false)
#Column(name = "username")
#XmlElement
private String username;
#Basic(optional = false)
#Column(name = "password")
private String password;
I thought that if I don't add #XmlElement annotation to password field, it won't be included into result. However, I got a bunch of "Class has two properties of the same name" errors during deployment.
This is because the default behaviour for XML generation is PUBLIC_MEMBER (http://java.sun.com/javaee/5/docs/api/javax/xml/bind/annotation/XmlAccessorType.html).
Since you are putting the #XmlElement on the fields, it is grabbing both your public getter/setter methods AND any field w/ #XmlElement on it. What you're likely going to want to is set the XmlAccessorType to either FIELD or NONE.
Annotate the class with
#XmlAccessorType(XmlAccessType.NONE)
Then annotate the fields you want to send with
#XmlElement(name="field_name")
There's actually a JAXB issue (that I can't find the reference to right now) that basically says that if you will be reading from XML, you'll want to annotate the setters and not the fields themselves.