JAXB解组集(集)
我测试和解组下面的Java对象:JAXB解组集(集)
框架类:
@XmlRootElement (name = "framework")
@XmlAccessorType(XmlAccessType.FIELD)
@Entity
public class Framework implements Comparable<Framework>, Serializable {
private static final long serialVersionUID = 1L;
@XmlTransient
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String frameworkName;
private String frameworkVersion;
private String frameworkDescription;
@XmlElementWrapper(name = "framework-domains")
private Set<FrameworkDomain> frameworkDomainList = new HashSet<>();
@XmlElementWrapper(name = "framework-comments")
private Set<Comment> comments = new HashSet<>();
(只包含的getter,setter和功能没有任何附加注释的nuber)
域类:
@XmlRootElement(name = "domain")
@XmlAccessorType(XmlAccessType.FIELD)
@Entity
public class FrameworkDomain implements Comparable<FrameworkDomain>, Serializable {
private static final long serialVersionUID = 1L;
@XmlTransient
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String domainName;
private String domainDescription;
@XmlElementWrapper(name = "domain-requirements")
private Set<Requirement> domainRequirements = new HashSet<>();
@XmlElementWrapper(name = "domain-comments")
private Set<Comment> domainComments = new HashSet<>();
要求CLA SS:
@XmlRootElement(name = "requirement")
@XmlAccessorType(XmlAccessType.FIELD)
@Entity
public class Requirement implements Comparable<Requirement>, Serializable {
private static final long serialVersionUID = 1L;
@XmlTransient
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String requirementName;
private String requirementDescription;
private String requirementGuidance;
@XmlElementWrapper(name = "sub-requirements")
private Set<Requirement> requirementSubrequirementList = new HashSet<>();
@XmlElementWrapper(name = "testing-procedures")
private Set<TestingProcedure> requirementTestingProceduresList = new HashSet<>();
@XmlElementWrapper(name = "requirement-comments")
private Set<Comment> comments = new HashSet<>();
编组和解组代码:
public static String exportFramework(Framework f) {
java.io.StringWriter s = new java.io.StringWriter();
try {
JAXBContext jc = JAXBContext.newInstance(Framework.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_ENCODING, "utf-8");
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(f, s);
} catch (Exception ex) {
ex.printStackTrace();
}
return s.toString();
}
public static Framework importFramework(java.io.InputStream xml) {
intelicompliance.model.Framework f = null;
try {
JAXBContext jc = JAXBContext.newInstance(Framework.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
f = (intelicompliance.model.Framework) unmarshaller.unmarshal(xml);
} catch (JAXBException ex) {
ex.printStackTrace();
}
return f;
}
当我名帅我已经创建了一个对象,它会生成以下XML:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<framework>
<frameworkName>PCI DSS</frameworkName>
<frameworkVersion>3.3</frameworkVersion>
<frameworkDescription>The Payment Card Industry Data Security Standard (PCI DSS) is a proprietary information security standard for organizations that handle branded credit cards from the major card schemes including Visa, MasterCard, American Express, Discover, and JCB.</frameworkDescription>
<framework-domains>
<frameworkDomainList>
<domainName>Domain 1a</domainName>
<domainDescription>Build and Maintain a Secure Network and Systems</domainDescription>
<domain-requirements></domain-requirements>
<domain-comments></domain-comments>
</frameworkDomainList>
<frameworkDomainList>
<domainName>Domain 2a</domainName>
<domainDescription>Protect Cardholder Data</domainDescription>
<domain-requirements/>
<domain-comments/>
</frameworkDomainList>
<frameworkDomainList>
<domainName>Domain 3a</domainName>
<domainDescription>Maintain a Vulnerability Management Program</domainDescription>
<domain-requirements/>
<domain-comments/>
</frameworkDomainList>
<frameworkDomainList>
<domainName>Domain 4a</domainName>
<domainDescription>Implement Strong Access Control Measures</domainDescription>
<domain-requirements/>
<domain-comments/>
</frameworkDomainList>
<frameworkDomainList>
<domainName>Domain 5a</domainName>
<domainDescription>Regularly Monitor and Test Networks</domainDescription>
<domain-requirements/>
<domain-comments/>
</frameworkDomainList>
<frameworkDomainList>
<domainName>Domain 6a</domainName>
<domainDescription>Maintain an Information Security Policy</domainDescription>
<domain-requirements/>
<domain-comments/>
</frameworkDomainList>
</framework-domains>
<framework-comments/>
</framework>
...这正是我期待。
但是,当我尝试将XML转换回对象时,只有一个域被包含在Set中 - 即导入(unmarshalling)过程在第一个节点后忽略XML节点。
有没有人有一个想法,为什么?或者,我做错了什么?
UPDATE 我已经改变了一些进展:
private Set<FrameworkDomain> frameworkDomainList = new HashSet<>();
到:
private List<FrameworkDomain> frameworkDomainList = new LinkedList<>();
现在进口的所有子元素预期。不过,我真的更喜欢使用Set。
JAXB是否将Set(s)与List(s)不同?
根据您的回答我的问题:
我的意思是什么,通过适当的是,你保证每一个对象,它是不一样的将返回不同的散列。
你的问题来自于你解组的每个对象都具有相同的hashCode,因此你的组认为每个元素都是等号,并且只保留一个(最后一个JAXB进程,顺便说一下)。
您应该可以通过将HashSet添加到没有ID的对象中来确认此行为,只应保留最后一个对象。
它也解释了为什么当您切换到链接列表时填充您的列表。
可以使用不同的hashCode方法或编组id来解决您的问题。请记住,您应始终重写equals()方法以及hashCode()方法,并确保a.equals(b)和a.hashCode == b.hashCode始终产生相同的结果。
你,我的朋友,是一位学者和先生们!你已经指出了问题和建议的解决方案! – JohnMarkh
您是否正确设置了对象中的hashCode()方法? –
不知道你的意思是“正确”...这里是代码: @Override public int hashCode(){ int hash = 0; hash + =(id!= null?id.hashCode():0); 返回散列; } – JohnMarkh