在POJO内部使用JAXB映射为XML的地图。

huangapple go评论93阅读模式
英文:

Map inside POJO to XML with JAXB

问题

我有一个像这样的产品POJO:

  1. @XmlRootElement(name = "o")
  2. @XmlAccessorType(XmlAccessType.FIELD)
  3. public class Product {
  4. @XmlAttribute
  5. private Integer avail;
  6. @XmlAttribute
  7. private Long id;
  8. @XmlAttribute
  9. private BigDecimal price;
  10. @XmlAttribute
  11. private String url;
  12. @XmlAttribute
  13. private Integer stock;
  14. private String category;
  15. private String title;
  16. private String description;
  17. @XmlElementWrapper(name = "attrs")
  18. @XmlElement(name = "a")
  19. private Map<String, String> attributes;
  20. //getters, setters, toString
  21. }

下一个类给我产品列表。

  1. @XmlRootElement(name = "offers")
  2. @XmlAccessorType(XmlAccessType.FIELD)
  3. public class Products {
  4. @XmlElement(name = "o")
  5. private List<Product> products = null;
  6. public List<Product> getProducts() {
  7. return products;
  8. }
  9. public void setProducts(List<Product> products) {
  10. this.products = products;
  11. }
  12. }

下一个类从数据库获取数据并将其作为产品列表返回:

  1. private Connection conn = null;
  2. private ResultSet rs = null;
  3. private PreparedStatement selectProducts = null;
  4. private Query query = new Query();
  5. private Map<String, String> attr = new HashMap<String , String>();
  6. private List<Product> mainList = new ArrayList<>();
  7. private DescCreator descCreator = new DescCreator(); //taking care of product html description
  8. public List<Product> listFiller() {
  9. try {
  10. conn = DriverManager.getConnection(connectionData);
  11. selectProducts = conn.prepareCall(query.getMainQuery());
  12. rs = selectProducts.executeQuery();
  13. while(rs.next()){
  14. Product product = new Product();
  15. product.setId(rs.getLong("products_id"));
  16. product.setPrice(rs.getBigDecimal("products_price_tax"));
  17. product.setUrl("https://www.link.com/" + rs.getString("products_id") + ".html");
  18. product.setAvail(rs.getInt("products_availability_id"));
  19. product.setStock(rs.getInt("products_quantity"));
  20. product.setCategory(rs.getString("categories_name"));
  21. product.setTitle(rs.getString("products_name"));
  22. product.setDescription(descCreator.descript(rs.getString("products_description")));
  23. attr.put(rs.getString("products_extra_fields_name"), rs.getString("products_extra_fields_value"));
  24. product.setAttributes(attr);
  25. mainList.add(product);
  26. }
  27. } catch (SQLException throwables) {
  28. throwables.printStackTrace();
  29. }
  30. return mainList;
  31. }

用于填充主列表的类(我的列表是从其他较小的列表构建的)。

  1. @XmlRootElement(name = "offers")
  2. @XmlAccessorType(XmlAccessType.PROPERTY)
  3. public class ListInitializer {
  4. //从其他较小的列表创建主列表的代码
  5. return mainList;
  6. }

以及主要的 marshal 类:

  1. public class MainMarshal {
  2. private ListInitializer mainListInitializer = new ListInitializer();
  3. private Products products = new Products();
  4. public void marshalMain() throws JAXBException, IOException {
  5. products.setProducts(mainListInitializer.generateMainXml());
  6. JAXBContext jaxbContext = JAXBContext.newInstance(Products.class);
  7. Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
  8. jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
  9. jaxbMarshaller.marshal(products, new File("filepath"));
  10. }
  11. }

我的代码的结果类似于这样:

  1. <offers>
  2. <o avail="1" id="1234" price="1234.00" url="some url" stock="1234">
  3. <category>PC</category>
  4. <title>Some product title</title>
  5. <desc>Some product description</desc>
  6. <attrs>
  7. <entry>
  8. <key>Map key</key>
  9. <value>Map value</value>
  10. </entry>
  11. <entry>
  12. <key>Map key</key>
  13. <value>Map value</value>
  14. </entry>
  15. <entry>
  16. <key>Map key</key>
  17. <value>Map value</value>
  18. </entry>
  19. </attrs>
  20. </o>
  21. </offers>

我需要的结果是这样的:

  1. <offers>
  2. <o avail="1" id="1234" price="1234.00" url="some url" stock="1234">
  3. <category>PC</category>
  4. <title>Some product title</title>
  5. <desc>Some product description</desc>
  6. <attrs>
  7. <a name="Map key">Map value</a>
  8. <a name="Map key">Map value</a>
  9. <a name="Map key">Map value</a>
  10. <a name="Map key">Map value</a>
  11. </attrs>
  12. </o>
  13. </offers>

有关如何实现这个结果的建议或指南吗?是否有改变标签名称(entrysetvalue)的方法?

英文:

I have POJO of product like this:

  1. @XmlRootElement(name = &quot;o&quot;)
  2. @XmlAccessorType(XmlAccessType.FIELD)
  3. public class Product {
  4. @XmlAttribute
  5. private Integer avail;
  6. @XmlAttribute
  7. private Long id;
  8. @XmlAttribute
  9. private BigDecimal price;
  10. @XmlAttribute
  11. private String url;
  12. @XmlAttribute
  13. private Integer stock;
  14. private String category;
  15. private String title;
  16. private String description;
  17. @XmlElementWrapper(name = &quot;attrs&quot;)
  18. @XmlElement(name = &quot;a&quot;)
  19. private Map&lt;String, String&gt; attributes;
  20. //getters, setters, toString
  21. }

Next class gives me list of products.

  1. @XmlRootElement(name = &quot;offers&quot;)
  2. @XmlAccessorType(XmlAccessType.FIELD)
  3. public class Products {
  4. @XmlElement(name = &quot;o&quot;)
  5. private List&lt;Product&gt; products = null;
  6. public List&lt;Product&gt; getProducts() {
  7. return products;
  8. }
  9. public void setProducts(List&lt;Product&gt; products) {
  10. this.products = products;
  11. }
  12. }

Next class gets data from database and return it as a product list:

  1. private Connection conn = null;
  2. private ResultSet rs = null;
  3. private PreparedStatement selectProducts = null;
  4. private Query query = new Query();
  5. private Map&lt;String, String&gt; attr = new HashMap&lt;String , String&gt;();
  6. private List&lt;Product&gt; mainList = new ArrayList&lt;&gt;();
  7. private DescCreator descCreator = new DescCreator(); //taking care of product html description
  8. public List&lt;Product&gt; listFiller() {
  9. try {
  10. conn = DriverManager.getConnection(connectionData);
  11. selectProducts = conn.prepareCall(query.getMainQuery());
  12. rs = selectProducts.executeQuery();
  13. while(rs.next()){
  14. Product product = new Product();
  15. product.setId(rs.getLong(&quot;products_id&quot;));
  16. product.setPrice(rs.getBigDecimal(&quot;products_price_tax&quot;));
  17. product.setUrl(&quot;https://www.link.com/&quot; + rs.getString(&quot;products_id&quot;) + &quot;.html&quot;);
  18. product.setAvail(rs.getInt(&quot;products_availability_id&quot;));
  19. product.setStock(rs.getInt(&quot;products_quantity&quot;));
  20. product.setCategory(rs.getString(&quot;categories_name&quot;));
  21. product.setTitle(rs.getString(&quot;products_name&quot;));
  22. product.setDescription(descCreator.descript(rs.getString(&quot;products_description&quot;)));
  23. attr.put(rs.getString(&quot;products_extra_fields_name&quot;), rs.getString(&quot;products_extra_fields_value&quot;));
  24. product.setAttributes(attr);
  25. mainList.add(product);
  26. }
  27. } catch (SQLException throwables) {
  28. throwables.printStackTrace();
  29. }
  30. return mainList;
  31. }

Class to populate main list (my list was built from other smaller lists).

  1. @XmlRootElement(name = &quot;offers&quot;)
  2. @XmlAccessorType(XmlAccessType.PROPERTY)
  3. public class listInitializer {
  4. //code to create main list from other smaller list
  5. return mainList;
  6. }
  7. }

And main marshal class:

  1. public class MainMarshal{
  2. private MainListInitializer mainListInitializer = new MainListInitializer();
  3. private Products products = new Products();
  4. public void marshalMain() throws JAXBException, IOException {
  5. products.setProducts(mainListInitializer.generateMainXml());
  6. JAXBContext jaxbContext = JAXBContext.newInstance(Products.class);
  7. Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
  8. jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
  9. jaxbMarshaller.marshal(products, new File(&quot;filepath&quot;));
  10. }
  11. }

Result of my code is something like this:

  1. &lt;offers&gt;
  2. &lt;o avail=&quot;1&quot; id=&quot;1234&quot; price=&quot;1234.00&quot; url=&quot;some url&quot; stock=&quot;1234&quot;&gt;
  3. &lt;category&gt;PC&lt;/category&gt;
  4. &lt;title&gt;Some product title&lt;/title&gt;
  5. &lt;desc&gt;Some product description&lt;/desc&gt;
  6. &lt;attrs&gt;
  7. &lt;entry&gt;
  8. &lt;key&gt;Map key&lt;/key&gt;
  9. &lt;value&gt;Map value&lt;/value&gt;
  10. &lt;/entry&gt;
  11. &lt;entry&gt;
  12. &lt;key&gt;Map key&lt;/key&gt;
  13. &lt;value&gt;Map value&lt;/value&gt;
  14. &lt;/entry&gt;
  15. &lt;entry&gt;
  16. &lt;key&gt;Map key&lt;/key&gt;
  17. &lt;value&gt;Map value&lt;/value&gt;
  18. &lt;/entry&gt;
  19. &lt;/atrts&gt;
  20. &lt;/o&gt;
  21. &lt;/offers&gt;

And i need this as a result:

  1. &lt;offers&gt;
  2. &lt;o avail=&quot;1&quot; id=&quot;1234&quot; price=&quot;1234.00&quot; url=&quot;some url&quot; stock=&quot;1234&quot;&gt;
  3. &lt;category&gt;PC&lt;/category&gt;
  4. &lt;title&gt;Some product title&lt;/title&gt;
  5. &lt;desc&gt;Some product description&lt;/desc&gt;
  6. &lt;attrs&gt;
  7. &lt;a name=&quot;Map key&quot;&gt;Map value&lt;/a&gt;
  8. &lt;a name=&quot;Map key&quot;&gt;Map value&lt;/a&gt;
  9. &lt;a name=&quot;Map key&quot;&gt;Map value&lt;/a&gt;
  10. &lt;a name=&quot;Map key&quot;&gt;Map value&lt;/a&gt;
  11. &lt;/atrts&gt;
  12. &lt;/o&gt;
  13. &lt;/offers&gt;

Any suggetions or guides how to achiev this result? Is there any way to change tag names: entry, set and value?

答案1

得分: 1

以下是翻译好的内容:

为此,您将需要使用XmlAdapter。

应创建以下bean:

  1. public class Entry {
  2. @XmlAttribute
  3. public String name;
  4. @XmlValue
  5. public String value;
  6. }
  7. public class MapWrapper {
  8. @XmlElement(name="a")
  9. public List<Entry> entry = new ArrayList<>();
  10. }

XML适配器:

  1. import java.util.Map;
  2. import java.util.TreeMap;
  3. import javax.xml.bind.annotation.adapters.XmlAdapter;
  4. public class MapAdapter extends XmlAdapter<MapWrapper, Map<String, String>> {
  5. @Override
  6. public Map<String, String> unmarshal(MapWrapper adaptedMap) throws Exception {
  7. Map<String, String> map = new TreeMap<>();
  8. adaptedMap.entry.forEach(entry -> {
  9. map.put(entry.name, entry.value);
  10. });
  11. return map;
  12. }
  13. @Override
  14. public MapWrapper marshal(Map<String, String> map) throws Exception {
  15. MapWrapper adaptedMap = new MapWrapper();
  16. map.entrySet().stream().map(mapEntry -> {
  17. Entry entry = new Entry();
  18. entry.name = mapEntry.getKey();
  19. entry.value = mapEntry.getValue();
  20. return entry;
  21. }).forEachOrdered(entry -> {
  22. adaptedMap.entry.add(entry);
  23. });
  24. return adaptedMap;
  25. }
  26. }

在类Product中,您需要更改属性映射的注解:

  1. @XmlElement(name="attrs")
  2. @XmlJavaTypeAdapter(MapAdapter.class)
  3. private Map<String, String> attributes;

这将产生以下输出:

  1. <attrs>
  2. <a name="key">value</a>
  3. </attrs>
英文:

For this purpose you'll need to use XmlAdapter.

Following beans should be created:

  1. public class Entry {
  2. @XmlAttribute
  3. public String name;
  4. @XmlValue
  5. public String value;
  6. }
  7. public class MapWrapper {
  8. @XmlElement(name=&quot;a&quot;)
  9. public List&lt;Entry&gt; entry = new ArrayList&lt;&gt;();
  10. }

XML Adapter:

  1. import java.util.Map;
  2. import java.util.TreeMap;
  3. import javax.xml.bind.annotation.adapters.XmlAdapter;
  4. public class MapAdapter extends XmlAdapter&lt;MapWrapper, Map&lt;String, String&gt;&gt; {
  5. @Override
  6. public Map&lt;String, String&gt; unmarshal(MapWrapper adaptedMap) throws Exception {
  7. Map&lt;String, String&gt; map = new TreeMap&lt;&gt;();
  8. adaptedMap.entry.forEach(entry -&gt; {
  9. map.put(entry.key, entry.value);
  10. });
  11. return map;
  12. }
  13. @Override
  14. public MapWrapper marshal(Map&lt;String, String&gt; map) throws Exception {
  15. MapWrapper adaptedMap = new MapWrapper();
  16. map.entrySet().stream().map(mapEntry -&gt; {
  17. Entry entry = new Entry();
  18. entry.key = mapEntry.getKey();
  19. entry.value = mapEntry.getValue();
  20. return entry;
  21. }).forEachOrdered(entry -&gt; {
  22. adaptedMap.entry.add(entry);
  23. });
  24. return adaptedMap;
  25. }
  26. }

In class Product you'll need to change annotations for attributes map:

  1. @XmlElement(name=&quot;attrs&quot;)
  2. @XmlJavaTypeAdapter(MapAdapter.class)
  3. private Map&lt;String, String&gt; attributes;

That will give following output:

  1. &lt;attrs&gt;
  2. &lt;a name=&quot;key&quot;&gt;value&lt;/a&gt;
  3. &lt;/attrs&gt;

huangapple
  • 本文由 发表于 2020年9月30日 17:12:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/64134435.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定