Sto cercando di leggere un file JSON come:JAXB ed eredità
{
"a": "abc",
"data" : {
"type" : 1,
...
}
}
dove la ... parte è sostituibile in base al tipo come:
{
"a": "abc",
"data" : {
"type" : 1,
"b" : "bcd"
}
}
o:
{
"a": "abc",
"data" : {
"type" : 2,
"c" : "cde",
"d" : "def",
}
}
Per la vita di me non riesco a capire le giuste annotazioni/classi JAXB da usare per far sì che ciò accada. Non ho problemi a spostare la variabile di tipo all'esterno del blocco dati, se necessario.
Sto usando Glassfish 3.1.2.2.
Edit:
Basato sul codice fornito da Perception ho fatto un rapido tentativo ... non funziona in GlassFish però:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = As.PROPERTY, property = "type")
@JsonSubTypes(
{
@JsonSubTypes.Type(value = DataSubA.class, name = "1"),
@JsonSubTypes.Type(value = DataSubB.class, name = "2")
})
@XmlRootElement
public abstract class Data implements Serializable
{
private static final long serialVersionUID = 1L;
public Data()
{
super();
}
}
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
public class DataSubA
extends Data
{
private static final long serialVersionUID = 1L;
@XmlElement
private BigDecimal expenditure;
public DataSubA() {
super();
}
public DataSubA(final BigDecimal expenditure) {
super();
this.expenditure = expenditure;
}
@Override
public String toString() {
return String.format("%s[expenditure = %s]\n",
getClass().getSimpleName(), getExpenditure());
}
public BigDecimal getExpenditure() {
return expenditure;
}
public void setExpenditure(BigDecimal expenditure) {
this.expenditure = expenditure;
}
}
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
public class DataSubB
extends Data
{
private static final long serialVersionUID = 1L;
@XmlElement
private String name;
@XmlElement
private Integer age;
public DataSubB()
{
super();
}
public DataSubB(final String name, final Integer age)
{
super();
this.name = name;
this.age = age;
}
@Override
public String toString()
{
return String.format("%s[name = %s, age = %s]\n",
getClass().getSimpleName(), getName(), getAge());
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
public class DataWrapper
{
@XmlElement
private Data data;
public Data getData() {
return data;
}
public void setData(Data data) {
this.data = data;
}
}
E un semplice post che prende in:
@Stateless
@Path("x")
public class Endpoint
{
@POST
@Consumes(
{
MediaType.APPLICATION_JSON,
})
@Produces(
{
MediaType.APPLICATION_JSON,
})
public String foo(final DataWrapper wrapper)
{
return ("yay");
}
}
Quando passo in JSON come:
{
"data" :
{
"type" : 1,
"expenditure" : 1
}
}
ottengo un messaggio del tipo:
Can not construct instance of Data, problem: abstract types can only be instantiated with additional type information
at [Source: [email protected]; line: 2, column: 5] (through reference chain: DataWrapper["data"])
Nessun cambiamento ...: -/ – TofuBeer
@TofuBeer - Prova ad aggiungere un '@ GET' per vedere che cosa il messaggio di risposta è. Quindi puoi confrontare questo con quello che stai inviando come richiesta. –
{ "dati": { "name": "A", "età": 42 }} – TofuBeer