Наследование JAXB, немаршал к подклассу упорядоченного класса

Я думаю, что это самый простой способ сделать это, используя JSON stringify, и это может быть лучшим решением в некоторых ситуациях:

JSON.stringify(a1) === JSON.stringify(a2);

Это преобразует объекты a1 и a2 в чтобы их можно было сравнить. Порядок очень важен в большинстве случаев, поскольку он может сортировать объект с помощью алгоритма сортировки, показанного в одном из приведенных выше ответов.

Пожалуйста, обратите внимание, что вы больше не сравниваете объект, а строковое представление объект. Это может быть не совсем то, что вы хотите.

42
задан Steve Kuo 7 March 2009 в 06:20
поделиться

5 ответов

Вы используете право JAXB 2.0? (начиная с JDK6)

существует класс:

javax.xml.bind.annotation.adapters.XmlAdapter<ValueType,BoundType>

, который может разделить на подклассы, и переопределение в соответствии с методами:

public abstract BoundType unmarshal(ValueType v) throws Exception;
public abstract ValueType marshal(BoundType v) throws Exception;

Пример:

public class YourNiceAdapter
        extends XmlAdapter<ReceiverPerson,Person>{

    @Override public Person unmarshal(ReceiverPerson v){
        return v;
    }
    @Override public ReceiverPerson marshal(Person v){
        return new ReceiverPerson(v); // you must provide such c-tor
    }
}

Использование сделано как следующее:

@Your_favorite_JAXB_Annotations_Go_Here
class SomeClass{
    @XmlJavaTypeAdapter(YourNiceAdapter.class)
    Person hello; // field to unmarshal
}

я вполне уверен, при помощи этого понятия, которое можно управлять процессом маршалинга/немаршалинга собой (включая выбор корректное [sub|super] тип для построения).

20
ответ дан ivan_ivanovich_ivanoff 23 September 2019 в 14:08
поделиться

Следующий отрывок является методом теста Junit 4 с зеленым светом:

@Test
public void testUnmarshallFromParentToChild() throws JAXBException {
  Person person = new Person();
  int age = 30;
  String name = "Foo";
  person.name = name;
  person.age= age;

  // Marshalling
  JAXBContext context = JAXBContext.newInstance(person.getClass());
  Marshaller marshaller = context.createMarshaller();

  StringWriter writer = new StringWriter();
  marshaller.marshal(person, writer);

  String outString = writer.toString();

  assertTrue(outString.contains("</person"));

  // Unmarshalling
  context = JAXBContext.newInstance(Person.class, RecieverPerson.class);
  Unmarshaller unmarshaller = context.createUnmarshaller();
  StringReader reader = new StringReader(outString);
  RecieverPerson reciever = (RecieverPerson)unmarshaller.unmarshal(reader);

  assertEquals(name, reciever.name);
  assertEquals(age, reciever.age);
}

важная часть является использованием JAXBContext.newInstance(Class... classesToBeBound) метод для контекста немаршалинга:

 context = JAXBContext.newInstance(Person.class, RecieverPerson.class);

С этим вызовом, JAXB вычислит ссылочное закрытие на определенных классах и распознает RecieverPerson. Тестовые передачи. И если Вы измените порядок параметров, то Вы доберетесь java.lang.ClassCastException (таким образом, они будут должны быть переданными в этом порядке).

20
ответ дан Pascal Thivent 23 September 2019 в 14:08
поделиться

Разделите Человека на подклассы дважды, однажды для получателя и однажды для отправителя, и только поместите XmlRootElement на эти подклассы (оставляющий суперкласс, Person, без XmlRootElement). Обратите внимание, что отправитель и получатель оба совместно используют те же базовые классы JAXB.

@XmlRootElement(name="person")
public class ReceiverPerson extends Person {
  // receiver specific code
}

@XmlRootElement(name="person")
public class SenderPerson extends Person {
  // sender specific code (if any)
}

// note: no @XmlRootElement here
public class Person {
  // data model + jaxb annotations here
}

[протестированный и подтвержденный для работы с JAXB]. Это обходит проблему, которую Вы отмечаете, когда несколько классов в иерархии наследования имеют аннотацию XmlRootElement.

Это - возможно также более опрятное и больше подхода OO, потому что он выделяет модель общих данных, таким образом, это не "обходное решение" вообще.

12
ответ дан 13ren 23 September 2019 в 14:08
поделиться

Так как у Вас действительно есть два отдельных приложения, скомпилируйте их с различными версиями класса "Человек" - с приложением для получателя, не имеющим @XmlRootElement(name="person") на Person. Мало того, что это ужасно, но и это побеждает пригодность для обслуживания, которую Вы хотели от использования того же определения Человека и для отправителя и для получателя. Его один плюс - то, что это работает.

-1
ответ дан 13ren 23 September 2019 в 14:08
поделиться

Я не уверен, почему Вы хотели бы сделать это... это не кажется весь настолько безопасным мне.

Рассматривают то, что произошло бы в ReceiverPerson, имеет дополнительные переменные экземпляра... тогда Вы волновали бы с (я предполагаю), те переменные, являющиеся пустым, 0, или ложь... и что, если пустой указатель не позволяется или число должно быть больше, чем 0?

я думаю, что Вы, вероятно, хотите сделать, читается в Человеке, и затем создайте новый ReceiverPerson из того (вероятно, предоставляют конструктору, который берет Человека).

3
ответ дан TofuBeer 23 September 2019 в 14:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: