/ / JAXB / Jersey vydanie s neslušnými komplexnými typmi rozhraní - java, jaxb, dres

JAXB / Jersey vydávajú s unmarshalingom zložité typy s rozhraniami - java, jaxb, dres

Bojujem s niekoľkými problémami maršal / unmarshall JSon a vyzerá to, že to nikdy nebude fungovať :(

Pozrite sa na prvé číslo:Mám triedu Response, ktorá obsahuje niekoľko polí: String error, String error_code a Object response. Trieda zodpovedná za vyplnenie všetkých údajov odpovedí, v prípade potreby vyplnenie chybových polí a ich odoslanie späť klientovi na ďalšiu analýzu.

"Objektová odpoveď" môže byť ľubovoľného typu (prečo Object? Pretože nepracoval s rozhraniami a to by bola druhá časť otázky)

útržok kódu:

   @XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Response
{
public static final String ERROR_FIELD_NAME = "error";
public static final String ERROR_CODE_FIELD_NAME = "error_code";
public static final String RESPONSE_FIELD_NAME = "response";

@XmlElement(name = Response.ERROR_CODE_FIELD_NAME)
private String errorCode;

@XmlElement(name = Response.ERROR_FIELD_NAME)
private String errorMessage;

@XmlElementRefs(
{@XmlElementRef(type = AClassResponse.class),
@XmlElementRef(type = BClassResponse.class)})
private Object entity;

a atď.

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlAdapter;


//@XmlRootElement(name = Response.RESPONSE_FIELD_NAME)
//@XmlJavaTypeAdapter(AClassResponse.Adapter.class)
@XmlRootElement
public class AClassResponse
{
private TargetObject target;


public TargetObject getTarget()
{
return target;
}


public void setTarget(TargetObject target)
{
this.target = target;
}
}

JSON 1 (for XmlElementRef AClassResponse.class ):
{
"error" : "",
"error_code" : "",
**"aClassResponse" :**
{ "target" :
{ "accountId" : "5bd0812b",
"id" : "6ccb6ae1-30c3-4aa0-8d1e-6ed61b6bb217",
"isCaseSensitive" : "false",
"maxNumberOfConnections" : "0",
"name" : "targetName",
"pathDelimiter" : "/",
"type" : "SMB"
}
}
}

JSON 1 (for XmlElementRef BClassResponse.class):
{
"error" : "",
"error_code" : "",
**"bClassResponse" :**
{ "target" :
{ "accountId" : "5bd0812b",
"id" : "6ccb6ae1-30c3-4aa0-8d1e-6ed61b6bb217",
"isCaseSensitive" : "false",
"maxNumberOfConnections" : "0",
"name" : "targetName",
"pathDelimiter" : "/",
"type" : "SMB"
}
}
}

Teraz je problém:

Pozrite sa na JSon vyššie, "aClassResponse": a "bClassResponse": sú vždy dynamické (znamená to, že názov je odvodený od názvu triedy) - to nie je to, čo potrebujem.

Mojím cieľom je dať tomuto názvu trvalé meno „odpoveď“, takže všetci vzdialení klienti o tom budú vedieť a budú sa spoliehať na toto meno.

Viem, opraviť, že môžem anotovať AClassResponse.class s @XmlRootElement (name = "odpoveď")A bude to fungovať, kým nebudete mať definovaných viac ako jeden @XmlElementRef.

Ak sú dve alebo viac, spôsobuje to problém so zaradením / odobratím a JAXB nevie, ktorá trieda, ktorá sa má naviazať, by sa mala naviazať na pole entity, pretože sa spolieha tiež na meno (name = "response").

@XmlElementRefs(
{@XmlElementRef(type = AClassResponse.class),
@XmlElementRef(type = BClassResponse.class)})
private Object entity;

zaobchádza sa s tým takto:

@XmlElementRefs(
{@XmlElementRef(name = "response", type = AClassResponse.class),
@XmlElementRef(name = "response", type = BClassResponse.class)})
private Object entity;

Predpokladajme, že sa jedná o správne správanie, a preto nemôžem urobiť nič, aby som zachoval to isté (name = "response") pre niektorý z typov objektov.

Dobre, pokúsil som sa to obísť zavedenímrozhranie namiesto Object type + @XmlJavaTypeAdapter (AClassResponse.Adapter.class) pre každú implementáciu - ani to však nefungovalo, čo vyvolalo výnimku, že rozhrania nie sú podporované atď.

Zdá sa, že tento článok môže do toho vniesť trochu svetla, http://jaxb.java.net/guide/Mapping_interfaces.html

ale zlyháva tiež s tým, že nemôže vytvoriť inštanciu abstraktnej triedy abstraktná trieda AbstractFooImpl

@XmlJavaTypeAdapter(AbstractFooImpl.Adapter.class)
interface IFoo {
...
}
**abstract class AbstractFooImpl implements IFoo {**
...

static class Adapter extends XmlAdapter<AbstractFooImpl,IFoo> {
IFoo unmarshal(AbstractFooImpl v) { return v; }
AbstractFooImpl marshal(IFoo v) { return (AbstractFooImpl)v; }
}
}

class SomeFooImpl extends AbstractFooImpl {
@XmlAttribute String name;
...
}

class AnotherFooImpl extends AbstractFooImpl {
@XmlAttribute int id;
...
}

class Somewhere {
public IFoo lhs;
public IFoo rhs;
}

Nejaké rady, ako to môžem vyriešiť? Prosím pomôžte..

Ďakujem.

odpovede:

0 pre odpoveď č. 1

JAXB nerobí rozhrania.Riešením sú buď generické alebo abstraktné triedy (anotované znakom @XmlTransient, aby JAXB ignoroval základnú triedu, a @XmlSeeAlso, aby namiesto toho používal konkrétne implementácie). To vyrieši časť Java, ale stále musíte opraviť časť rovnice XSD (nezabudnite, že JAXB vidí cez Jersey iba verziu XML vášho JSON).

Za týmto účelom môžete vo svojom poli použiť anotácie @XmlElementRef a @XmlElementRefs, aby sa XSD namapoval na výber konkrétnych implementácií.

@XmlTransient // JAXB doesn"t like abstract types, so do not map this type name
// XmlSeeAlso only required if BaseImpl/BaseImpl2 are not otherwise auto-discovered by JAXB
@XmlSeeAlso({BaseImpl.class, BaseImpl2.class })
public abstract class Base {
@XmlElement(name="still-works")
public String thisFieldWillStillBeMappedByJAXB;
}

@XmlRootElement("base-impl")
public class BaseImpl {}

@XmlRootElement("alternative")
public class BaseImpl2 {}

public class Complex<E extends Base> {
@XmlElementRefs({
@XmlElementRef(type=BaseImpl.class),
@XmlElementRef(type=BaseImpl2.class)
})
public E impl; // will be an instance of either "base-impl" or "alternative"
}

0 pre odpoveď č. 2

Môžete použiť @XmlElements anotáciu a postupujte takto:

@XmlElements({
@XmlElementRef(name = "response", type = AClassResponse.class),
@XmlElementRef(name = "response", type = BClassResponse.class)
})
private Object entity;