Как обернуть подсписку с помощью jaxb

При попытке сопоставить клиент- > порядок 1: n с jaxb 2.2.6 я бы хотел получить список заказов, заключенных в отдельный node "порядок".

в настоящее время результат:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
    <Customer>
       <id>100</id>
       <name>John Doe</name>
       <orders>
         <address>100 main street, smalltown, pa</address>
         <orderid>1100</orderid>
       </orders>
      <orders>
         <address>5 broadway, ny, ny</address>
         <orderid>1200</orderid>
       </orders> 
    </Customer>

но я хотел бы получить:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
    <Customer>
       <id>100</id>
       <name>John Doe</name>
       <orders>
         <order>
           <address>100 main street, smalltown, pa</address>
           <orderid>1100</orderid>
         </order>
         <order>
            <address>5 broadway, ny, ny</address>
            <orderid>1200</orderid>
         </order>
       </orders> 
    </Customer>

Что нужно изменить, чтобы получить этот результат?

Соответствующий исходный код имеет:

  • Интерфейс клиента
  • Реализация CustomerJaxbDao
  • Интерфейс заказа
  • Реализация OrderJaxbDao
  • TestCustomerWrite Junit4 Testcase

и использует эту реализацию jaxb:

            <!-- JAXB -->
    <dependency>
        <groupId>com.sun.xml.bind</groupId>
        <artifactId>jaxb-impl</artifactId>
        <version>2.2.6</version>
    </dependency>

Клиентский интерфейс:

/**
 * Copyright (C) 2011-2012 BITPlan GmbH
 * 
 * http://www.bitplan.com
 *
 * generated: 2012-10-15 15:12 with smartGENERATOR
 */
package com.bitplan.testentity;
import java.util.List;
import com.bitplan.testentity.Order;


/**
 * interface for Customer
 */
public interface Customer {
    // >>>{interface}{Customer}{Customer}
    // no implementation yet !!!
    // <<<{interface}{Customer}{Customer}
  /**
   * getter for name
   * @return name
   */
  public String getName();

  /**
   * setter for name
   * @param pname - new value for name
   */
  public void setName(String pname);

  /**
   * getter for id
   * @return id
   */
  public long getId();

  /**
   * setter for id
   * @param pid - new value for id
   */
  public void setId(long pid);

  /**
   * getter for orders
   * @return orders
   */
  public List<Order> getOrders();

  /**
   * setter for orders
   * @param porders - new value for orders
   */
  public void setOrders(List<Order> porders);

} // Customer

Интерфейс заказа:

/**
 * Copyright (C) 2011-2012 BITPlan GmbH
 * 
 * http://www.bitplan.com
 *
 * generated: 2012-10-15 at 23:59 with smartGENERATOR
 */
package com.bitplan.testentity;

/**
 * interface for Order
 */
public interface Order {
    // >>>{interface}{Order}{Order}
    // no implementation yet !!!
    // <<<{interface}{Order}{Order}
  /**
   * getter for orderid
   * @return orderid
   */
  public long getOrderid();

  /**
   * setter for orderid
   * @param porderid - new value for orderid
   */
  public void setOrderid(long porderid);

  /**
   * getter for shipping address
   * @return address
   */
  public String getAddress();

  /**
   * setter for shipping address
   * @param paddress - new value for shipping address
   */
  public void setAddress(String paddress);

} // Order

Реализация CustomerJaxbDao

/**
 * Copyright (C) 2011-2012 BITPlan GmbH
 * 
 * http://www.bitplan.com
 *
 * generated: 2012-10-15 at 23:51 with smartGENERATOR
 */
package com.bitplan.testentity.jaxb;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlElement;

import com.bitplan.testentity.Order;
import com.bitplan.testentity.Customer;

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

/**
 * JaxB Data access object for Customer
 * Entity: Customer for container testentity
 * Table: Customer
 */
@XmlRootElement(name="Customer")
public class CustomerJaxbDao implements Customer {
  /**
   * name
   */
  private String name;

  /**
   * id
   */
  private long id;

  /**
   * orders
   */
  private List<Order> orders=new ArrayList<Order>();

  /**
   * getter for name
   * @return name
   */
  @XmlElement(name="name")
  public String getName() { return name; };

  /**
   * setter for name
   * @param pname - new value for name
   */
  public void setName(String pname) { name=pname; };

  /**
   * getter for id
   * @return id
   */
  @XmlElement(name="id")
  public long getId() { return id; };

  /**
   * setter for id
   * @param pid - new value for id
   */
  public void setId(long pid) { id=pid; };

  /**
   * getter for orders
   * @return orders
   */
  @XmlElement(name="orders", type=OrderJaxbDao.class)
  public List<Order> getOrders() { return orders; };

  /**
   * setter for orders
   * @param porders - new value for orders
   */
  public void setOrders(List<Order> porders) { orders=porders; };


} // CustomerJaxbDao

Реализация OrderJaxbDao

/**
 * Copyright (C) 2011-2012 BITPlan GmbH
 * 
 * http://www.bitplan.com
 *
 * generated: 2012-10-15 with smartGENERATOR
 */
package com.bitplan.testentity.jaxb;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlElement;
import com.bitplan.testentity.Order;


/**
 * JaxB Data access object for Order
 * Entity: Order for container testentity
 * Table: Order
 */
@XmlRootElement(name="Order")
public class OrderJaxbDao implements Order {
  /**
   * orderid
   */
  private long orderid;

  /**
   * shipping address
   */
  private String address;

  /**
   * getter for orderid
   * @return orderid
   */
  @XmlElement(name="orderid")
  public long getOrderid() { return orderid; };

  /**
   * setter for orderid
   * @param porderid - new value for orderid
   */
  public void setOrderid(long porderid) { orderid=porderid; };

  /**
   * getter for shipping address
   * @return address
   */
  @XmlElement(name="address")
  public String getAddress() { return address; };

  /**
   * setter for shipping address
   * @param paddress - new value for shipping address
   */
  public void setAddress(String paddress) { address=paddress; };


} // OrderJaxbDao

TestCustomerWrite Тест-сценарий Junit4

package com.bitplan.storage.jaxb;

import static org.junit.Assert.*;

import java.io.StringWriter;

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

import org.junit.Test;

import com.bitplan.testentity.Customer;
import com.bitplan.testentity.Order;
import com.bitplan.testentity.jaxb.CustomerJaxbDao;
import com.bitplan.testentity.jaxb.OrderJaxbDao;

/**
 * 
 * @author wf
 *
 */
public class TestCustomerWrite {

    @Test
    public void test() throws JAXBException {
        Customer customer=new CustomerJaxbDao();
        customer.setId(100);
        customer.setName("John Doe");
        long orderid=1000;
        String[] addresses={"100 main street, smalltown, pa","5 broadway, ny, ny"};
        for (String address:addresses) {
            Order order=new OrderJaxbDao();
            order.setAddress(address);
            order.setOrderid(orderid+=100);
            customer.getOrders().add(order);
        }
        JAXBContext jaxbContext = JAXBContext.newInstance(CustomerJaxbDao.class);
        Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

        // output pretty printed
        jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        StringWriter sw=new StringWriter();
        jaxbMarshaller.marshal(customer, sw);
        System.out.println(sw);

    }

}

Ответ 1

Вместо

/**
 * getter for orders
 * @return orders
 */
@XmlElement(name="orders", type=OrderJaxbDao.class)
public List<Order> getOrders() { return orders; };

Вам нужно

/**
 * getter for orders
 * @return orders
 */
@XmlElement(name="order", type=OrderJaxbDao.class)
@XmlElementWrapper(name="orders")
public List<Order> getOrders() { return orders; };

Имя @XmlElementWrapper - это имя элемента упаковки (заказов), а имя @XmlElement - это имя элемента для каждой записи внутри обертки (порядок).

Ответ 2

Это похоже на трюк:

  @XmlElementWrapper(name="orders")
  @XmlElement(name="order", type=OrderJaxbDao.class)
  public List<Order> getOrders() { return orders; };

улучшенный CustomerJaxbDao

/**
 * Copyright (C) 2011-2012 BITPlan GmbH
 * 
 * http://www.bitplan.com
 * 
 * generated: 2012-10-16 12:20 with smartGENERATOR
 */
package com.bitplan.testentity.jaxb;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlElement;
import com.bitplan.testentity.Customer;

import java.util.List;
import com.bitplan.testentity.Order;
import javax.xml.bind.annotation.XmlElementWrapper;
import java.util.ArrayList;

/**
 * JaxB Data access object for Customer
 * Entity: Customer for container testentity
 * Table: Customer
 */
@XmlRootElement(name="Customer")
public class CustomerJaxbDao implements Customer {
  /**
   * name
   */
  private String name;

  /**
   * id
   */
  private long id;

  /**
   * orders
   */
  private List<Order> orders=new ArrayList<Order>();

  /**
   * getter for name
   * @return name
   */
  @XmlElement(name="name")  
  public String getName() { return name; };

  /**
   * setter for name
   * @param pname - new value for name
   */
  public void setName(String pname) { name=pname; };

  /**
   * getter for id
   * @return id
   */
  @XmlElement(name="id")  
  public long getId() { return id; };

  /**
   * setter for id
   * @param pid - new value for id
   */
  public void setId(long pid) { id=pid; };

  /**
   * getter for orders
   * @return orders
   */
  @XmlElementWrapper(name="orders")
  @XmlElement(name="order", type=OrderJaxbDao.class)
  public List<Order> getOrders() { return orders; };

  /**
   * setter for orders
   * @param porders - new value for orders
   */
  public void setOrders(List<Order> porders) { orders=porders; };


} // CustomerJaxbDao

Ответ 3

Похоже, вы хотите обернуть заказ в своем классе CustomerJaxbDao.

@XmlElementWrapper( name="orders" )
@XmlElement(name="order", type=OrderJaxbDao.class)
public List<Order> getOrders() { return orders; };

Можете сделать то, что хотите.