1

私はJSonをマーシャル/アンマーシャルするいくつかの問題に苦しんでいます、そしてそれは私がそれを動かすことは決してないようです:(

最初の問題を見てください:文字列エラー、文字列error_code、オブジェクト応答のいくつかのフィールドを含むクラスResponseがあります。応答するすべてのデータを入力し、必要に応じてエラーフィールドに入力し、さらに分析するためにクライアントに送り返す責任があるクラス。

「オブジェクト応答」はどのタイプでもかまいません(インターフェイスで機能しなかったため、なぜオブジェクトなのか、それが質問の2番目の部分になるため)

コードスニペット:

   @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;

や。。など...

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"
            } 
         }
    }

今問題:

上記のJSonを見てください。「aClassResponse」:「bClassResponse」:は常に動的です(名前がクラス名から派生していることを意味します)。これは私が必要としているものではありません。

私の目標は、この名前に永続的な名前「response」を付けることです。これにより、リモートクライアントはこれを認識し、この名前に依存します。

@XmlRootElement(name = "response")でAClassResponse.classに注釈を付けることができることを修正するために知っています。これは、複数の@XmlElementRefが定義されるまで機能します。

2つ以上の場合、これによりマーシャリング/アンマーシャリングで問題が発生し、JAXBは名前にも依存するため、バインドするクラスをエンティティフィールドにバインドする必要があるかどうかわかりません(name = "response")

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

それはこのように扱います:

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

これが正しい動作であり、どのオブジェクトタイプでも同じ(name = "response")を維持するために私ができることは何もないと仮定します。

OK、実装ごとにオブジェクトタイプ+ @XmlJavaTypeAdapter(AClassResponse.Adapter.class)の代わりにインターフェイスを導入することで回避しようとしましたが、どちらも機能せず、インターフェイスがサポートされていないなどの例外が発生しました...

この記事は、これにいくらかの光を当てることができるようです、http://jaxb.java.net/guide/Mapping_interfaces.html

しかし、抽象クラスをインスタンス化できないと言って失敗します抽象クラス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;
}

これを回避する方法についてのアドバイスはありますか?助けてください..

ありがとうございました。

4

2 に答える 2

0

JAXBはインターフェースを行いません。解決策は、ジェネリッククラスまたは抽象クラスのいずれかです(JAXBが基本クラスを無視するように@XmlTransientで注釈を付け、代わりに特定の実装を使用するように@XmlSeeAlsoで注釈を付けます)。これでJavaの部分は解決されますが、方程式のXSDの部分を修正する必要があります(JAXBはJSONのXMLバージョンのみをJerseyで表示することに注意してください)。

そのために、フィールドで@XmlElementRefおよび@XmlElementRefsアノテーションを使用して、XSDが特定の実装の選択にマップされるようにすることができます。

@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"
}
于 2012-06-29T01:59:42.823 に答える
0

注釈を使用@XmlElementsして、次のことを行うことができます。

@XmlElements({
    @XmlElementRef(name = "response", type = AClassResponse.class),
    @XmlElementRef(name = "response", type = BClassResponse.class)
})
private Object entity;
于 2012-06-29T01:51:09.130 に答える