3

JAXBアノテーションを使用したJacksonのObjectMapperで問題が発生しています。具体的には、インターフェイスの一般的な情報を含むコレクションがあり、XMLからの入力を逆シリアル化することはできますが、Jacksonでは(JAXBイントロスペクターを使用して)できません。たぶん、いくつかの構成プロパティまたはJAXBアノテーションが欠落しているだけですか?問題は、「抽象型は追加の型情報でのみインスタンス化できる」ということです。型情報を含む@XmlElementRef(または@XmlElement)でこの問題を処理できると思いましたが、明らかにそうではありません。

可能であれば、JAXBアノテーションのみを使用したいことに注意してください。たとえば、@JsonTypeInfoまたは@JsonDeserializeを使用するのが最後になります。

IEntry.java:

@XmlSeeAlso(Entry.class)
public interface IEntry {
    String getValue();
}

Entry.java:

@XmlRootElement(name = "entry")
public class Entry implements IEntry {

    @XmlElement(name = "value")
    String value;

    public Entry() {
    }

    public Entry(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

Aggregator.java:

@XmlRootElement(name = "aggregator")
public class Aggregator {

    @XmlElementRef(type = Entry.class)
    private Set<IEntry> entries;

    public Aggregator() {
    }

    public Aggregator(Set<IEntry> entries) {
        this.entries = entries;
    }

    public Set<IEntry> getEntries() {
        return entries;
    }
}

試験方法:

@Test
    public void testSerialization() throws Exception {
        ObjectMapper om = new ObjectMapper();
        AnnotationIntrospector intr = new JaxbAnnotationIntrospector();
        om.getDeserializationConfig().withAnnotationIntrospector(intr);

        String json = "{\"entries\":[{\"value\":\"X\"},{\"value\":\"Y\"},{\"value\":\"Z\"}]}\";\n}";
        Aggregator agr = om.readValue(json, Aggregator.class);
    }

すべての応答をありがとう

4

2 に答える 2

2

注: 私はEclipseLink JAXB(MOXy)のリーダーであり、JAXB(JSR-222)エキスパートグループのメンバーです。

ジャクソンがこのユースケースをサポートしているかどうかはわかりませんが、@XmlElementRef間違って使用しているようです。クラスに関連付けられたルート要素名を使用@XmlElementRefする場合、インスタンス化するインスタンスを決定するために使用されます。例の場合、ノードはアノテーションentriesと一致しません。@XmlRootElement(name="entry")

次のオプションのいずれかを試すことができます(これらはすべてMOXyのJSONバインディングで機能します。http://blog.bdoughan.com/2011/08/json-binding-with-eclipselink-moxy.htmlを参照してください

オプション1-@XMLRootElementオンに変更Entry

@XmlRootElement(name = "entries")
public class Entry implements IEntry {

    @XmlElement(name = "value")
    String value;

    public Entry() {
    }

    public Entry(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

オプション#2-JSONドキュメントを変更する

{"entry":[{"value":"X"},{"value":"Y"},{"value":"Z"}]}}

オプション#3-@XMLElement代わりに使用@XMLElementRef

注釈を使用する場合は、@XmlElement注釈に依存する代わりに、フィールド/プロパティでノード名を指定できます@XmlRootElement。また、フィールドに注釈を付ける場合は@XmlAccessorType(XmlAccessType.FIELD)、タイプレベルで指定する必要があります。

import java.util.Set;
import javax.xml.bind.annotation.*;

@XmlRootElement(name = "aggregator")
@XmlAccessorType(XmlAccessType.FIELD)
public class Aggregator {

    @XmlElement(type = Entry.class)
    private Set<IEntry> entries;

    public Aggregator() {
    }

    public Aggregator(Set<IEntry> entries) {
        this.entries = entries;
    }

    public Set<IEntry> getEntries() {
        return entries;
    }
}

詳細については

于 2012-09-12T13:27:45.160 に答える
1
import org.codehaus.jackson.map.annotate.JsonDeserialize;  

@JsonDeserialize(as = Entry.class)
public interface IEntry {
   String getValue();
}  
于 2012-09-12T12:44:15.217 に答える