Quindi sto lavorando su un'API dati RESTful usando Java, Hibernate, annotazioni JPA, annotazioni JAX-RS, annotazioni JAXB, Jersey e il parser JSON Jackson .Come aggirare l'incapacità di Jackson di gestire riferimenti diretti nei bean JPA
Dopo aver provato varie configurazioni delle notazioni MAPPING e NATURAL JSON fornite da Jersey, alla fine ho deciso di utilizzare il parser Jackson JSON. Jackson sarebbe perfetto tranne per questo problema ...
Il problema che ho riscontrato è che Jackson non funziona con le annotazioni JAXB, "@XmlID" e "@XmlIDREF", che uso per indicare la mia entità relazioni, e anche se "@JsonBackReference" e "@JsonManagedReference" aiutano con questo. La combinazione sembra crollare quando si tratta di proprietà dirette di autoreferenzialità.
Sembra che sarebbe un problema abbastanza comune. Come mai qualcuno di voi ha aggirato questa limitazione con Jackson?
Con il mio POJO come ...
@XmlRootElement
public class Employee implements Serializable {
private Date lastUpdatedOn;
private Employee lastUpdatedBy;
private Integer empId;
@JoinColumn(nullable=false)
@OneToOne
@XmlIDREF
public Employee getLastUpdatedBy() {
return createdBy;
}
public void setLastUpdatedBy(Employee lastUpdatedBy) {
this.lastUpdatedBy = lastUpdatedBy;
}
@Temporal(TemporalType.TIMESTAMP)
public Date getLastUpdatedOn() {
return createdOn;
}
public void setLastUpdatedOn(Date lastUpdatedOn) {
this.lastUpdatedOn = lastUpdatedOn;
}
@XmlID
@XmlJavaTypeAdapter(IntegerAdapter.class)
public Integer getEmpId() {
return empId;
}
public void setEmpId(Integer empId) {
this.empId = empId;
}
}
... e il seguente EmployeeResource ...
@Path("/Employees")
public class EmployeeResource {
private List<Employee> employees;
public List<Employee> getEmployees() {
return employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
@GET
@Path("/{empId}")
public Response getEmployees(
@Context UriInfo ui
, @PathParam("id") Integer empId
) {
this.employees = HibernateUtil.pagedQuery(
Employee.class
, new ArrayList() {
Restrictions.eq("empId",empId)
}
);
return Response.ok(this).build();
}
}
mia risorsa JAX-RS produrrà il seguente errore
org.codehaus.jackson.map.JsonMappingException: Direct self-reference leading to cycle (through reference chain: resources.EmployeeResource["employees"]->java.util.ArrayList[0]->entities.Employee["lastUpdatedBy"])
... ma voglio produrre ...
{
"employees" : [ {
"lastUpdatedOn" : 1331149770737,
"lastUpdatedBy" : 10150,
"empId" : 10150,
} ],
}
Grazie in anticipo a tutti!
NOTE:
- uso l'IntegerAdapter.class per convertirlo in una stringa in modo che funzioni con l'annotazione @XmlID.
- Le classi Employee e EmployeeResource descritte in precedenza sono solo versioni abbreviate della mia implementazione effettiva, ma rappresentano la parte della mia implementazione che è rilevante per questo problema di autoreferenziale diretto.
EDIT # 1 2012/03/10 Mi dispiace, nella mia prima versione di questa domanda mi ero confuso tra la versione che ho con la notazione naturale di Jersey vs la versione che ho in esecuzione con Jackson. Ho rivisto la mia domanda per riflettere più accuratamente il problema diretto autoreferenziale che ho con Jackson.
Penso che la tua domanda non sia pertinente a '@ XmlID' così com'è, ma alle basi JSON. JSON non supporta i tipi, quindi "" 10150 "' (stringa) e '10150' (numeri interi, ma non supportati) sono" uguali ". –
Non sarei d'accordo. JSON ha una comprensione di tipi come Object, Array, String e number, www.json.org. – hypno7oad
Mi dispiace male. Quello di cui hai bisogno credo sia il convertitore da 'Date' a' int'. Vedere l'esempio [qui] (http://blog.seyfi.net/2010/03/how-to-control-date-formatting-when.html). –