Jaxb: How to replace a class/binding in given object tree while unmarshalling

后端 未结 3 1481
不知归路
不知归路 2020-12-20 00:44

I have a given set of classes to unmarshall a xml into an object tree. Now I get a extended xml and want to replace one class in the object tree with an extended version.

相关标签:
3条回答
  • 2020-12-20 01:19

    A similar topic is discussed here: JAXB inheritance, unmarshal to subclass of marshaled class

    With jackson 2.8.6 you can just write something like

    @Test
    public void readXmlToSelfDefinedPojo2() throws Exception {
    
        ObjectMapper mapper = new XmlMapper();
        ExtAdress pojo = mapper.readValue(
                        Thread.currentThread().getContextClassLoader().getResourceAsStream("52109685.xml"),
                        ExtAdress.class);
        System.out.println(toString(pojo));
    }
    
    public String toString(Object obj) throws JsonGenerationException, JsonMappingException, IOException{
        StringWriter w = new StringWriter();
        new ObjectMapper().configure(SerializationFeature.INDENT_OUTPUT, true).writeValue(w, obj);
        return w.toString();
    }
    

    It will print

    {
      "systemId" : "on the 4",
      "type" : "test"
    }
    

    for

    <?xml version="1.0" encoding="UTF-8"?>
      <RootNode_001>
    <systemId>on the 4</systemId>
    <systemName>give me some more</systemName>
    <type>test</type>
    <person>
        <firstname>James</firstname>
        <lastname>Brown</lastname>
        <address>
            <street>Funky</street>
            <city>Town</city>
            <type>HOME</type> <!-- this is the new field -->
        </address>
    </person>
    </RootNode_001>
    

    and

    @JsonIgnoreProperties(ignoreUnknown = true)
    public class ExtAdress extends Adress {
        public String type;
        public ExtAdress() {
        }
    }
    

    and

    @JsonIgnoreProperties(ignoreUnknown = true)
    public class Adress {
        public String systemId;
    
        public Adress() {
        }
    }
    
    0 讨论(0)
  • 2020-12-20 01:27

    You should do XML schema versioning instead of this, however it is difficult to do it well. There is a pdf in the linked article, you should read it.

    I did the "Option 3 Change the schema's targetNamespace" in the past, in this way, you can do the following:

    you have different targetNamespaces for every version:

    targetNamespace="http://www.exampleSchema.com/v1.0"
    targetNamespace="http://www.exampleSchema.com/v1.1"
    ...
    

    and you can generate the necessary JAXB classes for each namespace in different group:

    com.example.schema.generated.v10
    com.example.schema.generated.v11
    ...
    

    From here it is up to you how to try to read it:

    • you can make a contract, that the file must ends with the version of the schema: file1_v10.xml, file2_v11.xml
    • you can try to read with the latest JAXB classes, if it fails, the previous and so on
    • you can the first n. line as text of the file, and parse the targetNamespace, and apply the right JAXB
    • or you have another option and so on...

    (of course, you have to handle each version separately after unmarshalling, which is not necessarily bad)

    OR

    you can decide so that you are using only 1 schema, and one can only extend the schema with optional (minOccurs="0") elements, it is ugly, and has some limitations, but sometimes it is enough.

    OR

    Or, you can do it in a different way: you can use another XML framework, that supports schema versioning, like this one: JMRI or JiBX (They are not necessary current or actively developed, just wanted to show some examples. What I really wanted to link is an another one, but unfortunately I forgot its name).

    0 讨论(0)
  • 2020-12-20 01:28

    Changing the xml with extAddress instead address will do the trick.

    0 讨论(0)
提交回复
热议问题