как сопоставить структуру bean-компонента с другой схемой с помощью jax-rs

у меня есть эта фасоль

@XmlRootElement
class Test {
   boolean someValue;
   List<Field> fields;
}

Я хотел бы сериализовать его как

<fields>
   <field>
       <name>someValue</name>
       <value>...</value>
   </field>
</fields>
<fields>
   <field>
       <name>otherValue</name>
       <value>...</value>
   </field>
</fields>

(или как json)

Как мне это сделать, предпочтительно используя аннотации jaxb?

Я использую трикотаж, но ответ не обязательно должен быть специфичным для него.


person ymajoros    schedule 04.05.2011    source источник
comment
Какие типы объектов находятся в списке полей?   -  person bdoughan    schedule 04.05.2011
comment
Полезный комментарий, я только что отредактировал вопрос, чтобы он был ближе к моему реальному использованию.   -  person ymajoros    schedule 04.05.2011
comment
Мой пример из реальной жизни лучше объясняется в этом вопросе: using-jersey-usi" title="как использовать некоторую косвенность при преобразовании json в java bean с использованием jersey usi">stackoverflow.com/questions/5820028/   -  person ymajoros    schedule 04.05.2011
comment
Вам также нужно загрузить эту структуру из XML? И что такое корневой элемент?   -  person bdoughan    schedule 04.05.2011
comment
Да, мне также нужно иметь возможность загрузить его. Корневой элемент может быть элементом по умолчанию.   -  person ymajoros    schedule 04.05.2011


Ответы (1)


Как насчет следующего?

Используя EclipseLink JAXB (MOXy), вы можете сделать следующее. Примечание. Я технический руководитель MOXy.

Тест

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlRootElement
@XmlType(propOrder={"someValue", "fields"})
@XmlAccessorType(XmlAccessType.FIELD)
class Test {

    @XmlJavaTypeAdapter(SomeValueAdapter.class)
    @XmlPath("fields[1]")
    boolean someValue;

    @XmlJavaTypeAdapter(FieldsAdapter.class)
    List<Field> fields = new ArrayList<Field>();

    public Boolean isSomeValue() {
        return someValue;
    }

    public void setSomeValue(boolean someValue) {
        this.someValue = someValue;
    }

    public List<Field> getFields() {
        return fields;
    }

    public void setFields(List<Field> fields) {
        this.fields = fields;
    }

    public void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
        for(Field field : fields) {
            if("someValue".equals(field.getName())) {
                someValue = Boolean.valueOf(field.getValue());
                fields.remove(field);
            }
        }
    }

}

Поле

public class Field {

    private String name;
    private String value;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

}

Некоторое значение адаптера

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class SomeValueAdapter extends XmlAdapter<AdaptedField, Boolean> {

    @Override
    public Boolean unmarshal(AdaptedField v) throws Exception {
        String value = v.getField().getValue();
        return Boolean.valueOf(value);
    }

    @Override
    public AdaptedField marshal(Boolean v) throws Exception {
        AdaptedField adaptedField = new AdaptedField();
        Field field = new Field();
        field.setName("someValue");
        field.setValue(String.valueOf(v));
        adaptedField.setField(field);
        return adaptedField;
    }

}

Адаптер полей

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class FieldsAdapter extends XmlAdapter<AdaptedField, Field> {

    @Override
    public Field unmarshal(AdaptedField v) throws Exception {
        return v.getField();
    }

    @Override
    public AdaptedField marshal(Field v) throws Exception {
        AdaptedField adaptedField = new AdaptedField();
        adaptedField.setField(v);
        return adaptedField;
    }

}

Адаптированное поле

public class AdaptedField {

    private Field field;

    public Field getField() {
        return field;
    }

    public void setField(Field field) {
        this.field = field;
    }

}

Демо

импортировать java.io.File;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Test.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Test test = (Test) unmarshaller.unmarshal(new File("input.xml"));

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(test, System.out);
    }

}

входной файл.xml

<?xml version="1.0" encoding="UTF-8"?>
<test>
   <fields>
      <field>
         <name>someValue</name>
         <value>true</value>
      </field>
   </fields>
   <fields>
      <field>
         <name>otherValue</name>
         <value>1</value>
      </field>
   </fields>
   <fields>
      <field>
         <name>anotherValue</name>
         <value>2</value>
      </field>
   </fields>
</test>

Для получения дополнительной информации

person bdoughan    schedule 04.05.2011
comment
Приятно знать, что это можно сделать таким образом. Мне бы очень хотелось, чтобы не было зависимости (поскольку моя настоящая проблема заключается в написании клиента Jira для отдыха с меньшим количеством/отсутствием зависимостей). Нет стандартного способа сделать это? Кроме того, будет ли это работать с json? - person ymajoros; 04.05.2011
comment
@ymajoros — вы можете использовать Jettison с любой реализацией JAXB для создания/потребления JSON (bdoughan.blogspot.com/2011/04/jaxb-and-json-via-jettison.html), Джерси делает это автоматически на стороне сервера. Используя только прямые API-интерфейсы JAXNB, вам, вероятно, потребуется создать промежуточную модель и преобразовать ее в/из нее. - person bdoughan; 04.05.2011
comment
Я уже использую это. На самом деле, я использовал xml в этом вопросе, чтобы попытаться задать его по-другому, поскольку мой первоначальный вопрос, похоже, не имел полезных ответов. Но я действительно использую json. Могу ли я использовать MOXy с json (наверное, нет)? Могу ли я использовать MOXy только для некоторых целей, не заменяя при этом jaxb для остальной части моего приложения? - person ymajoros; 05.05.2011
comment
@ymajoros — JAXB (JSR-222) — это спецификация (bdoughan .blogspot.com/2010/07/jaxb-xml-binding-standard.html), а MOXy — это реализация JAXB. MOXy, как и любую реализацию JAXB, можно использовать с JSON через что-то вроде Jettison (bdoughan.blogspot.com/2011/04/jaxb-and-json-via-jettison.html). У вас есть другая реализация JAXB для каждого JAXBContext, инструкции по указанию MOXy в качестве поставщика JAXB см.: bdoughan.blogspot.com/2011/05/ - person bdoughan; 05.05.2011