java - जैक्सन xml मॉड्यूल: एक @ जैक्सन XmlText संपत्ति के साथ अपरिवर्तनीय प्रकार को दूर करना




jackson (2)

मैं json के रूप में और xml के रूप में एक अपरिवर्तनीय प्रकार को क्रमबद्ध करना चाहता हूं:

सीरियल किए गए JSON समान है:

{
    "text" : "... the text..."
}

और सीरियल किए गए XML समान है:

 <asText>_text_</asText>

(ध्यान दें कि पाठ xml का तत्व पाठ है)

जावा ऑब्जेक्ट की तरह है:

@JsonRootName("asText")
@Accessors(prefix="_")
public static class AsText {

    @JsonProperty("text") @JacksonXmlText
    @Getter private final String _text;

    public AsText(@JsonProperty("text") final String text) {
        _text = text;
    }
}

सावधान रहें कि _text संपत्ति अंतिम है (इसलिए ऑब्जेक्ट अपरिवर्तनीय है) और इसके लिए @JacksonXmlText साथ एनोटेट किया @JacksonXmlText है ताकि एक्सएमएल एलिमेंट के पाठ के रूप में सीरियल किया जा सके

वस्तु अपरिवर्तनीय होने के नाते, पाठ से एक निर्माता की आवश्यकता है और निर्माता के तर्क @JsonProperty साथ एनोटेट किया जाना चाहिए

    public AsText(@JsonProperty("text") final String text) {
        _text = text;
    }

जब serializing / deserializing JSON से / सब कुछ ठीक काम करता है ... समस्या उत्पन्न होती है जब / से XML / से deserializing:

 // create the object
 AsText obj = new AsText("_text_");

 // init the mapper
 XmlMapper mapper = new XmlMapper();

 // write as xml
 String xml = mapper.writeValueAsString(obj);
 log.warn("Serialized Xml\n{}",xml);

 // Read from xml
 log.warn("Read from Xml:");
 AsText objReadedFromXml = mapper.readValue(xml,
                                              AsText.class);
 log.warn("Obj readed from serialized xml: {}",
          objReadedFromXml.getClass().getName());

अपवाद है:

    com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "" (class r01f.types.url.UrlQueryStringParam), not marked as ignorable (2 known properties: "value", "name"])

ऐसा लगता है कि XML मॉड्यूल वस्तु की रचनाकार की तरह एनोटेट की जरूरत है:

    public AsText(@JsonProperty("") final String text) {
        _text = text;
    }

लेकिन यह काम नहीं करता है:

    com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `test.types.SerializeAsXmlElementTextTest$AsText` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)

JSON से deserialize करने के लिए कंस्ट्रक्टर के तर्क पर टिप्पणी @JsonProperty("text") की आवश्यकता है

... मैं यह कैसे काम करने के लिए कर सकता हूँ


संपत्ति के लिए एक सार्वजनिक भर्तीकर्ता को जोड़ने का प्रयास करें मुझे विश्वास है कि deserialization समस्या को ठीक करना चाहिए

@JsonRootName("asText")
@Accessors(prefix = "_")
public static class AsText {

    @JsonProperty("text")
    @JacksonXmlText
    @Getter
    private final String _text;

    public AsText(@JsonProperty("text") final String text) {
        _text = text;
    }

    public String getText() {
        return _text;
    }
}

दरअसल, यह लेटरक और जैक्सन के इन संस्करणों के साथ, एक गेटर भी जोड़े बिना काम करता है।

<dependencies>
    <dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-xml</artifactId>
        <version>2.9.0</version>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.16.18</version>
    </dependency>
</dependencies>

ऐसा लगता है कि आपकी समस्या का मुख्य कारण यह है कि आप एक ही समय में JSON और XML सीरियलाइजेशन का उपयोग करने की कोशिश करते हैं, लेकिन विभिन्न विन्यास के साथ। दुर्भाग्य से, XmlMapper प्राप्त होता है और सभी JSON- विशिष्ट कॉन्फ़िगरेशन को प्राप्त करता है (और आप इसे ओवरराइड कर सकते हैं लेकिन इसे XML- विशिष्ट एनोटेशन से साफ़ नहीं कर सकते) जो आपके संघर्ष का कारण है। ऐसा लगता है कि @JsonAlias में @JsonAlias एनोटेशन का उपयोग करने के लिए इसका सबसे सरल तरीका आसपास काम करना है यह थोड़ा हैकी है लेकिन यह काम करता है। यहां एक न्यूनतम उदाहरण है (बिना Lombok) जो मेरे लिए काम करता है:

@JsonRootName("asText")
public static class AsText {

    @JsonProperty("text")
    @JacksonXmlText
    private final String _text;

    public AsText(@JsonAlias("") @JsonProperty("text") final String text) {
        _text = text;
    }

    @JsonIgnore
    public String getText() {
        return _text;
    }

    @Override
    public String toString() {
        return "AsText{" +
                "_text='" + _text + '\'' +
                '}';
    }
}

ध्यान दें कि मैंने @JsonIgnore को @JsonIgnore को भी जोड़ @JsonIgnore है क्योंकि और मुझे आपके द्वारा अनुरोधित एक्सएमएल प्रारूप नहीं मिला है (और आप वही कर सकते हैं जिस पर ऑब्जेक्ट में लंबोक के onMethod का प्रयोग किया गया है)।

एक साधारण परीक्षण के लिए:

public static void main(String[] args) throws IOException {
    // create the object
    AsText obj = new AsText("123_text_");

    // init the mapper
    //ObjectMapper mapper = new ObjectMapper();
    XmlMapper mapper = new XmlMapper();

    // write as xml
    String xml = mapper.writeValueAsString(obj);
    System.out.println("Serialized Xml\n" + xml);

    // Read from xml
    AsText objReadedFromXml = mapper.readValue(xml, AsText.class);
    System.out.println("Read from Xml: " + objReadedFromXml);
}

मुझे निम्न आउटपुट मिलता है:

सीरियललाइज्ड एक्सएमएल
<AsText> 123_text _ </ asText>
Xml से पढ़ें: AsText {_text = '123_text_'}





jackson