【问题标题】:jackson List of subclasses deserialisationjackson 子类列表反序列化
【发布时间】:2016-08-05 17:06:55
【问题描述】:

我正在开发一个 web 服务,我应该提供 xml 作为响应,我为此使用了 jackson。我遇到了一个问题,我有一个抽象类:

package com.spinner.jackson;
import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText;

public class ClientObject {

    @JacksonXmlElementWrapper(useWrapping = false)
    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
    private List<MyItem> accounts;

    public ClientObject(List<MyItem> pl) {
        this.accounts = pl;
    }

    public ClientObject() {
        this.accounts = new ArrayList<MyItem>();
    }

    @JsonDeserialize(using = CustomDeserial.class)
    public void setL(List<MyItem> l) {
        this.accounts = l;
    }

    public List<MyItem> getAccounts() {
        // TODO Auto-generated method stub
        return this.accounts;
    }
}

然后我有如下子类:

包 com.spinner.jackson;

import javax.xml.bind.annotation.XmlRootElement;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;

@JacksonXmlRootElement(localName="itemA")
public class MySubItemA extends MyItem {

    public MySubItemA() {
        super();
        // TODO Auto-generated constructor stub
    }

    public MySubItemA(int id, String name) {
        super(id, name);
        // TODO Auto-generated constructor stub
    }

    private String itemAProperty1;
    private String itemAProperty2;

    public String getItemAProperty1() {
        return this.itemAProperty1;
    }

    public void setItemAProperty1(String itemAProperty1) {
        this.itemAProperty1 = itemAProperty1;
    }

    public String getItemAProperty2() {
        return this.itemAProperty2;
    }

    public void setItemAProperty2(String itemAProperty2) {
        this.itemAProperty2 = itemAProperty2;
    }

    @JsonCreator
    public MySubItemA(@JsonProperty("id")int id, @JsonProperty("name")String name, @JsonProperty("itemAProperty1")String p1, @JsonProperty("itemAProperty2")String p2) {
        super(id, name);
        this.itemAProperty1 = p1;
        this.itemAProperty2 = p2;
    }

}

另一个子类

package com.spinner.jackson;

import javax.xml.bind.annotation.XmlRootElement;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;

@JacksonXmlRootElement(localName="itemB")
public class MySubItemB extends MyItem {

    private int itemBProperty1;
    private String itemBProperty2;

    public int getItemBProperty1() {
        return this.itemBProperty1;
    }

    public void setItemBProperty1(int itemBProperty1) {
        this.itemBProperty1 = itemBProperty1;
    }

    public String getItemBProperty2() {
        return this.itemBProperty2;
    }

    public void setItemBProperty2(String itemBProperty2) {
        this.itemBProperty2 = itemBProperty2;
    }

    public MySubItemB(@JsonProperty("id")int id, @JsonProperty("name")String name, @JsonProperty("itemBProperty1")int p1, @JsonProperty("itemBProperty2")String p2) {
        super(id, name);
        this.itemBProperty1 = p1;
        this.itemBProperty2 = p2;
    }
}

和一个客户端类如下:

package com.spinner.jackson;
import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText;

public class ClientObject {

    @JacksonXmlElementWrapper(useWrapping = false)
    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
    private List<MyItem> accounts;

    public ClientObject(List<MyItem> pl) {
        this.accounts = pl;
    }

    public ClientObject() {
        this.accounts = new ArrayList<MyItem>();
    }

    @JsonDeserialize(using = CustomDeserial.class)
    public void setL(List<MyItem> l) {
        this.accounts = l;
    }

    @JsonDeserialize(using = CustomDeserial.class)
    public List<MyItem> getAccounts() {
        // TODO Auto-generated method stub
        return this.accounts;
    }
}

MyItem 类:

    package com.spinner.jackson;

import javax.xml.bind.annotation.XmlRootElement;

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;

@XmlRootElement
public abstract class MyItem {


    public MyItem() {
        super();
        // TODO Auto-generated constructor stub
    }

    private int id;
    private String name;

    public int getId() {
        return this.id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public MyItem(int id, String name) {
        this.id = id;
        this.name = name;
    }

}

上面生成输出xml如下

<ClientObject>
    <accounts>
        <MySubItemA>
            ....
        </MySubItemA>
    </accounts>
    <accounts>
        <MySubItemB>
            ....
        </MySubItemB>
    </accounts>
</ClientObject>

即使我使用的是@JacksonXmlElementWrapper(useWrapping = false),有没有办法删除 &lt;accounts&gt; 包装器,如果我删除此注释,它也会执行以下操作

<ClientObject>
    <accounts>
        <accounts>
            <MySubItemA>
                ....
            </MySubItemA>
        </accounts>
        <accounts>
            <MySubItemB>
                .....
            </MySubItemB>
        </accounts>
    </accounts>
</ClientObject>

所以最终输出应该是

<ClientObject>
        <MySubItemA>
            ....
        </MySubItemA> 
        <MySubItemB>
            ....
        </MySubItemB> 
</ClientObject>

感谢您的帮助。

最好的问候 赛义德

【问题讨论】:

  • 你错过了抽象类 MyItem。
  • 谢谢,更新问题

标签: java xml jackson


【解决方案1】:

我能够弄清楚,所以我认为它可以帮助其他人:

我创建了序列化器

package com.spinner.jackson;

import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

public class MySerial extends JsonSerializer<ClientObject>
{
   public void serialize(ClientObject value, JsonGenerator jgen,
SerializerProvider provider)
       throws IOException, JsonProcessingException
   {
       jgen.writeObjectFieldStart(value.getClass().getSimpleName()); 
       jgen.writeObjectField(value.getAccounts().get(0).getClass().getSimpleName(), value.getAccounts().get(0)); 
       jgen.writeObjectField(value.getAccounts().get(1).getClass().getSimpleName(), value.getAccounts().get(1)); 
       jgen.writeObjectField(value.getAccounts().get(2).getClass().getSimpleName(), value.getAccounts().get(2)); 
       jgen.writeObjectField(value.getAccounts().get(3).getClass().getSimpleName(), value.getAccounts().get(3)); 

   }

}

接下来我在 ClientObject.java 中做了以下操作:

package com.spinner.jackson;

import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;

@JsonSerialize(using = CustomDeserial.class)
public class ClientObject {

    @JacksonXmlElementWrapper(useWrapping = false)
    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
    private List<MyItem> accounts;

    public ClientObject(List<MyItem> pl) {
        this.accounts = pl;
    }

    public ClientObject() {
        this.accounts = new ArrayList<MyItem>();
    }

    public void setL(List<MyItem> l) {
        this.accounts = l;
    }

    public List<MyItem> getAccounts() {
        return this.accounts;
    }
}

瞧,它成功了,希望这对某人有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-08
    • 2017-11-06
    • 1970-01-01
    • 2011-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多