当前位置: 首页 > 知识库问答 >
问题:

使用jaxb将自定义xml映射到java包括继承和hashmap

太叔志尚
2023-03-14

我喜欢xml

<Data>
<Protocol1
    var1="aaa"
    var2="bbb"
/>
<Protocol2
    var3="vv"
    var4="ff"
/>
</Data>

我们有像Protocol1,Protocol2这样的课程。。etc派生自基类协议。喜欢

@XmlRootElement(name="Protocol1")
class Protocol1 extends Protocol
{
    @XmlAttribute
    String var1;

    @XmlAttribute
    String var2;
}
class Protocol
{
}

类数据可以具有协议列表或映射。对于映射键将像“原型1”和值将是原型1类的对象。

@XmlRootElement(name="Data")
class Data
{
    @XmlJavaTypeAdapter(MapAdapter.class)
   Map<String,Protocol> protocolMap;
}

我试着做http://blog.bdoughan.com/2013/06/moxys-xmlvariablenode-using-maps-key-as.html但没有成功。如何使用变量节点和继承一起进行反编组。请引导。当前代码是:

//Adapter
public class MapAdapter extends XmlAdapter<List<ProtocolBase>,Map<String,ProtocolBase>>{
    @Override
    public List<ProtocolBase> marshal(Map<String,ProtocolBase> map){
        return new ArrayList<ProtocolBase>(map.values());
    }

    @Override
    public Map<String,ProtocolBase> unmarshal(List<ProtocolBase> lst){
        Map<String,ProtocolBase> map = new HashMap<>();
        for(ProtocolBase p : lst){
            map.put(p.getClass().getSimpleName(),p);
        }
        return map;
    }
}
//Base Class
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({ArrayList.class,Protocol1.class})
public class ProtocolBase {

    public ProtocolBase() {
        // TODO Auto-generated constructor stub
    }
}
//Derived class
@JsonRootName( "Protocol1")
@XmlAccessorType(XmlAccessType.FIELD)
public class Protocol1 extends ProtocolBase{

    @XmlAttribute(name="Name")
    @JsonProperty("Name")
    private String _name;
}
@JsonRootName( "Protocol2")
@XmlAccessorType(XmlAccessType.FIELD)
public class Protocol2 extends ProtocolBase{

    @XmlAttribute(name="Name")
    @JsonProperty("Name")
    private String _name;
}


//Main class
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Data")
@JsonRootName("Data")
@XmlSeeAlso({ArrayList.class,Protocol1.class,ProtocolBase.class})
public class Data {

   @XmlJavaTypeAdapter(MapAdapter.class)
    @XmlElements({
           @XmlElement(name="Protocol1",type=Protocol1.class)
       })
    private Map<String,ProtocolBase> protocolList = new HashMap<String, ProtocolBase>();

}

// Usage
device = new Data();
Protocol1 p1 = new Protocol1();
p1.set_name("ADT");


Protocol2 p2 = new Protocol2();
p2.set_name("ADT1");



device.getProtocolList().put("Protocol1",(SSDeviceProtocol) p1);
device.getProtocolList().put("Protocol2",(SSDeviceProtocol) p2);

JAXBContext jc = (JAXBContext) JAXBContext.newInstance();
Marshaller m = jc.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
m.marshal(device, System.out);

//Expected output
<Data>
<Protocol1 Name="ADT"/> 
<Protocol2 Name="ADT1"/>    
</Data>

共有1个答案

赵镜
2023-03-14

根据您的JAXB实现,您有两种解决方案:

  1. 使用参考JAXB实现

通过参考实现,您可以这样做:

@XmlRootElement(name="Data")
class Data
{
   @XmlJavaTypeAdapter(MapAdapter.class)
   @XmlElements({
       @XmlElement(name="Protocol1",type=Protocol1.class),
       @XmlElement(name="Protocol2",type=Protocol2.class),
       ....
   })
   Map<String,Protocol> protocolMap;
}

您的适配器应该扩展XmlAdapter

public class MapAdapter extends XmlAdapter<List<Protocol>,Map<String,Protocol>>{
    @Override
    public List<Protocol> marshal(Map<String,Protocol> map){
        return new ArrayList<Protocol>(map.values());
    }

    @Override
    public Map<String,Protocol> unmarshal(List<Protocol> lst){
        Map<String,Protocol> map = new HashMap<>();
        for(Protocol p : lst){
            map.put(p.getClass().getSimpleName(),p);
        }
        return map;
    }
}

此解决方案的问题是必须列出@XmlElements注释中的每个扩展类。

Blaise Doughan的示例使用自定义JAXB实现,如果您愿意使用它,可以使用以下解决方案:

@XmlRootElement(name="Data")
class Data
{
   @XmlJavaTypeAdapter(MapAdapter.class)
   @XmlPath(".")
   Map<String,Protocol> protocolMap;
}

不过要小心,当您使用@XmlPath(“.”)时,快速搜索主题会导致当前打开的bug@XmlJavaTypeAdapter结合使用。

此外,您应该在“协议”类上使用@XmlAccessorType,而不是@XmlRootElement,它应该保留给表示根XML元素的对象。

 类似资料:
  • 我从一个xml模式生成java类,对于一个复杂类型,我希望jaxb使用一个现有的类,我有一个外部绑定定制文件。自定义类被解组为正确的,除了该类型的单个属性,该属性从未在java类中填充。 下面是类型/类问题的演示。 模式中定义的内容是: 读取匹配xml文件的代码段是: 在这个xml中阅读: 使用JAXB生成的Thing类(不使用自定义xjb),输出符合预期: 使用只有getters的自定义Thin

  • 问题内容: 我有一个包含循环的对象图。我如何让JAXB处理呢?我尝试在子类中使用批注,但JAXB编组器仍检测到周期。 问题答案: 使用JAXB的好处是它是具有多个实现的标准运行时(就像JPA一样)。 如果使用EclipseLink JAXB(MOXy),则可以使用许多扩展来处理JPA实体,包括双向关系。这是使用MOXy @XmlInverseReference批注完成的。它的作用类似于元帅上的@X

  • 我的域名: 我的DTO: 我的地图绘制程序如下所示: 但是,我得到了以下错误: 目标名称“Framework.system”的类型Framework中的未知属性“system”。你是说“框架外部化”吗?目标名称为“Framework.availability”的Framework类型中的未知属性“availability”。你是说“框架外部化”吗?

  • 例如,我有以下接口映射器: 在代码中,您可以看到映射和一些默认方法,其中包含其他映射。如何在Mapstruct映射中使用这些方法,以便Mapstruct使用这些方法在字段中填充值?

  • 1. 前言 本节课程和大家一起学习继承映射。通过本节课程的学习,你将了解到: 什么是继承映射; 实现继承映射的 3 种方案。 2. 继承映射 学习继承映射之前,需要搞清楚什么是继承映射? 继承是 OOP 中的概念,其目的除了复用代码之外,还用来描述对象在现实世界中的关系。 为了更好地讲解继承映射,咱们再在数据库中创建一张老师表。数据库中多了一张表,按照使用 Hibernate 的套路,理所当然应该

  • 我有一个像这样的json,它嵌套在其中一个字段中- 我创建了一个自定义类, 在我的服务类中,我正在读取json并将其映射到我的EmailTemplate类中,但是映射失败了。这里有什么可以用的? 例外情况: 我试着添加 但这也不起作用。