JAXB and inheritance work when marshaling; but not parallelization

I want marshal / unmarshal objects of a class that inherits another form.

I start with the class Thing:

import java.util.List;

public class Thing {
  private List<String> strings;

  public List<String> getStrings() {
    return strings;
  }

  public void setStrings(List<String> strings) {
    this.strings = strings;
  }
}

I extend this class and annotate it with JAXB annotations.

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

@XmlRootElement
public class JaxbThing extends Thing {

  // @XmlElementWrapper(name = "list")
  @XmlElementWrapper(name = "strings")
  @XmlElement(name = "string")
  public List<String> getStrings() {
    return super.getStrings();
  }

  public void setStrings(List<String> string) {
    super.setStrings(string);
  }
}

Then I run the following marshalling / disassembling program:

import java.io.File;
import java.util.Arrays;
import javax.xml.bind.*;

public class Main {
  public static void main(String[] args) {
    JaxbThing t = new JaxbThing();
    t.setStrings(Arrays.asList("a", "b", "c"));
    try {
      File f = new File("jaxb-file.xml");

      JAXBContext context = JAXBContext.newInstance(JaxbThing.class);

      Marshaller m = context.createMarshaller();
      m.marshal(t, f);

      Unmarshaller um = context.createUnmarshaller();
      JaxbThing t2 = (JaxbThing) um.unmarshal(f);

      System.out.println(t2.getStrings());  // I expect to see [a, b, c]

    } catch (JAXBException e) {
      e.printStackTrace();
    }
  }
}

XML file content:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxbThing>
    <strings>
        <string>a</string>
        <string>b</string>
        <string>c</string>
    </strings>
</jaxbThing>

Everything seems right. But the unmarshaling result surprises me, because the console shows:

[
    ]

When I expected to see [a, b, c]

If I annotate a property stringsas follows:

  @XmlElementWrapper(name = "list")
  // @XmlElementWrapper(name = "strings")
  @XmlElement(name = "string")
  public List<String> getStrings() {
    return super.getStrings();
  }

Then the console shows the expected [a, b, c].

I assume that JMXB unmarshaler uses the class Thinginstead JaxbThingto untie the contents of the XML file. In fact, if I annotate class Thingc @XmlTransient, I get the expected result.

JAXB.

- , ? .

+4
2

, . JAXB , JAXBThing

  • , strings ( String), strings.
  • , strings ( JAXBThing, String strings.

setStrings JAXBThing, , , , ( , , ).

Thing, @XmlTransient.

import java.util.List;
import javax.xml.bind.annotation.XmlTransient;

@XmlTransient
public class Thing {
  private List<String> strings;

  public List<String> getStrings() {
    return strings;
  }

  public void setStrings(List<String> strings) {
      System.out.println("Thing" + strings);
    this.strings = strings;
  }

}

+2

. , . , setStrings . , , , .

. . , , unmarshalling.

Thing

import java.util.List;

public class Thing {
  private List<String> strings;

  public List<String> getStrings() {
    return strings;
  }

  public void setStrings(List<String> strings) {
    /*new*/ System.out.printf("Thing.setStrings called. Prev. this.strings: %s (size %s). Received strings param: %s", this.strings, (this.strings!=null ? this.strings.size():"null"),strings);
    this.strings = strings;
    /*new*/ System.out.printf(". New this.strings: %s (size %s).%n%n", this.strings, (this.strings!=null ? this.strings.size():"null"));
  }
}

JaxbThing

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

@XmlRootElement
public class JaxbThing extends Thing {

  // @XmlElementWrapper(name = "list")
  @XmlElementWrapper(name = "strings")
  @XmlElement(name = "string")
  public List<String> getStrings() {
    return super.getStrings();
  }

  public void setStrings(List<String> string) {
    /*new*/ System.out.printf("JaxbThing.setStrings called. Received strings param: %s (size %s)%n",string,(string !=null?string.size():"null"));
    super.setStrings(string);
  }
}

:

import java.io.File;
import java.util.Arrays;
import javax.xml.bind.*;

public class Main {
  public static void main(String[] args) {    
    System.out.println("---- Initiallizing");
    JaxbThing t = new JaxbThing();
    t.setStrings(Arrays.asList("a", "b", "c"));
    try {
      File f = new File("jaxb-file.xml");

      JAXBContext context = JAXBContext.newInstance(JaxbThing.class);

      System.out.println("---- Marshalling");
      Marshaller m = context.createMarshaller();
      m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);   /*new*/
      m.marshal(t, f);

      System.out.println("---- UnMarshalling");
      Unmarshaller um = context.createUnmarshaller();
      JaxbThing t2 = (JaxbThing) um.unmarshal(f);

      System.out.println("---- Showing results");
      System.out.println(t2.getStrings());  // I expect to see [a, b, c]

    } catch (JAXBException e) {
      e.printStackTrace();
    }
  }
}

( ):

1  ---- Initiallizing
2  JaxbThing.setStrings called. Received strings param: [a, b, c] (size 3)
3  Thing.setStrings called. Prev. this.strings: null (size null). Received strings param: [a, b, c]. New this.strings: [a, b, c] (size 3).
4  
5  ---- Marshalling
6  ---- UnMarshalling
7  JaxbThing.setStrings called. Received strings param: [] (size 0)
8  Thing.setStrings called. Prev. this.strings: null (size null). Received strings param: []. New this.strings: [] (size 0).
9  
10 JaxbThing.setStrings called. Received strings param: [
       ] (size 1)
11 Thing.setStrings called. Prev. this.strings: [
       ] (size 1). Received strings param: [
       ]. New this.strings: [
       ] (size 1).
12 
13 ---- Showing results
14 [
         ]

unmarshalling JaxbThing, JaxbThing.setStrings ( 7). , Thing.setStrings ( 8). (this.strings) . JaxbThing.setStrings ( 10), , '\n' 4 ( , XML ). :

  • JaxbThing.setStrings ( ).
  • JaxbThing.setStrings ( 10) Thing.setStrings ( 11). this.strings 0 , Thing.setStrings 8. "\n" 4 , .

, ?

0

All Articles