使用 XStream 反序列化泛型类型

发布于 2024-12-02 04:51:13 字数 1944 浏览 3 评论 0原文

我正在尝试使用 XStream 反序列化对具有通用类型字段的类的 xml 响应。

例如,我有类 Response

class Response<T extends BaseDTO>{
    int id;
    T field;

    public int getId(){
        return id;
    }
    public T getField(){
        return field;
    }
}

class B extends BaseDTO{}

class C extends BaseDTO{}

public abstract class XStreamFactory{
    public static <T extends BaseDTO> XStream initXStream(Class<T> c){
        XStream xstream = new XStream(new DomDriver());
        xstream.alias("response-root", Response.class);
        if(c.equals(B.class)){
            xstream.alias("specific-response-b", B.class);
        else
            xstream.alias("specific-response-c", C.class);

    xstream = addAliases(xstream, c);
    return xstream;
    }

    // we want to process the annotations declared on type c
    protected static XStream addAliases(XStream xstream, Class<?> c){       
        while (c != null) {
            xstream.processAnnotations(c);
            c = c.getSuperclass();
        }
        return xstream;
    }
}

要反序列化响应,我执行以下操作:

XStream xstream = XStreamFactory.initializeXStream(B.class);
Response<B> resp = (Response<B>) xstream.fromXML(response);

下面是我得到的 xml 响应:

<response-root>
    <id></id>
    <specific-response-b>
        //... content specific for class B
    </specific-response-b>
</response-root>

<response-root>
    <id></id>
    <specific-response-c>
        //... content specific for class c
    </specific-response-c>
</response-root>

上面的代码不会反序列化响应。它引发以下异常:

 com.thoughtworks.xstream.converters.ConversionException: Element specific-response-b of type B is not defined as field in type Response

你们能提供有关如何实现我想要的目标的任何指示吗? 谢谢。

I'm trying to use XStream to deserialize a xml response to a class that has a generic type field.

For example I have class Response

class Response<T extends BaseDTO>{
    int id;
    T field;

    public int getId(){
        return id;
    }
    public T getField(){
        return field;
    }
}

class B extends BaseDTO{}

class C extends BaseDTO{}

public abstract class XStreamFactory{
    public static <T extends BaseDTO> XStream initXStream(Class<T> c){
        XStream xstream = new XStream(new DomDriver());
        xstream.alias("response-root", Response.class);
        if(c.equals(B.class)){
            xstream.alias("specific-response-b", B.class);
        else
            xstream.alias("specific-response-c", C.class);

    xstream = addAliases(xstream, c);
    return xstream;
    }

    // we want to process the annotations declared on type c
    protected static XStream addAliases(XStream xstream, Class<?> c){       
        while (c != null) {
            xstream.processAnnotations(c);
            c = c.getSuperclass();
        }
        return xstream;
    }
}

To deserialize the response I do the following:

XStream xstream = XStreamFactory.initializeXStream(B.class);
Response<B> resp = (Response<B>) xstream.fromXML(response);

Below are the xml responses that I get:

<response-root>
    <id></id>
    <specific-response-b>
        //... content specific for class B
    </specific-response-b>
</response-root>

or

<response-root>
    <id></id>
    <specific-response-c>
        //... content specific for class c
    </specific-response-c>
</response-root>

The code above does not deserialize the response. It throws the following exception:

 com.thoughtworks.xstream.converters.ConversionException: Element specific-response-b of type B is not defined as field in type Response

Can you guys provide any pointers on how to achieve what I want?
Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

深巷少女 2024-12-09 04:51:13

XStream 没有这个问题。您可能正在执行某种自定义编组。下面是编组和解组您上面指定的类的示例:

public static void main(String[] args) {
    Response<B> responseB = new Response<B>(5, new B());
    String xml = new XStream().toXML(responseB);
    System.out.println("marshalled:\n" + xml);
    Response<B> resultB = (Response<B>) new XStream().fromXML(xml);
    System.out.println("unmarshalled: " + resultB);

    Response<C> responseC = new Response<C>(10, new C());
    xml = new XStream().toXML(responseC);
    System.out.println("marshalled:\n" + xml);
    Response<C> resultC = (Response<C>) new XStream().fromXML(xml);
    System.out.println("unmarshalled: " + resultC);
}

static class Response<T extends Foo> {
    int id;
    T field;

    Response(int id, T field) {
        this.id = id;
        this.field = field;
    }

    public int getId() { return id; }
    public T getField() { return field; }
}

static class Foo {}

static class B extends Foo {}

static class C extends Foo {}

输出 - 由于没有别名和 toString(),所以有点混乱:

marshalled:
<rds.testbed.XStreamReadingNamespaceAttributes_-Response>
  <id>5</id>
  <field class="rds.testbed.XStreamReadingNamespaceAttributes$B"/>
</rds.testbed.XStreamReadingNamespaceAttributes_-Response>
unmarshalled: rds.testbed.XStreamReadingNamespaceAttributes$Response@1cc7b00c
marshalled:
<rds.testbed.XStreamReadingNamespaceAttributes_-Response>
  <id>10</id>
  <field class="rds.testbed.XStreamReadingNamespaceAttributes$C"/>
</rds.testbed.XStreamReadingNamespaceAttributes_-Response>
unmarshalled: rds.testbed.XStreamReadingNamespaceAttributes$Response@3d66aa18

XStream doesn't have a problem with this. It's probably some kind of custom marshalling that you're doing. Here's an example of marshalling and unmarshalling the classes you specified above:

public static void main(String[] args) {
    Response<B> responseB = new Response<B>(5, new B());
    String xml = new XStream().toXML(responseB);
    System.out.println("marshalled:\n" + xml);
    Response<B> resultB = (Response<B>) new XStream().fromXML(xml);
    System.out.println("unmarshalled: " + resultB);

    Response<C> responseC = new Response<C>(10, new C());
    xml = new XStream().toXML(responseC);
    System.out.println("marshalled:\n" + xml);
    Response<C> resultC = (Response<C>) new XStream().fromXML(xml);
    System.out.println("unmarshalled: " + resultC);
}

static class Response<T extends Foo> {
    int id;
    T field;

    Response(int id, T field) {
        this.id = id;
        this.field = field;
    }

    public int getId() { return id; }
    public T getField() { return field; }
}

static class Foo {}

static class B extends Foo {}

static class C extends Foo {}

The output--a little messy because of no aliasing and no toString():

marshalled:
<rds.testbed.XStreamReadingNamespaceAttributes_-Response>
  <id>5</id>
  <field class="rds.testbed.XStreamReadingNamespaceAttributes$B"/>
</rds.testbed.XStreamReadingNamespaceAttributes_-Response>
unmarshalled: rds.testbed.XStreamReadingNamespaceAttributes$Response@1cc7b00c
marshalled:
<rds.testbed.XStreamReadingNamespaceAttributes_-Response>
  <id>10</id>
  <field class="rds.testbed.XStreamReadingNamespaceAttributes$C"/>
</rds.testbed.XStreamReadingNamespaceAttributes_-Response>
unmarshalled: rds.testbed.XStreamReadingNamespaceAttributes$Response@3d66aa18
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文