如何使用jaxb注释使用Jersey将json解组为java bean时使用一些间接

我正在试图解散一些收到的json(来自Jira restful web service)。

问题是:“问题”具有“摘要”属性和字段列表。

摘要不作为接收的json中的属性存在,而是作为“fields”属性的值。 我坚持要对这个结构进行解组:

@XmlRootElement class Issue { String summary; List fields; // getters/setters and lots of other fields } 

收到JSON:

 { "expand":"html", "self":"https://example.com/jira/rest/api/latest/issue/XYZ-1234", "key":"XYZ-1234", "fields": { "summary": { "name":"summary", "type":"java.lang.String", "value":"test 1234" }, "customfield_10080": { "name":"Testeur", "type":"com.atlassian.jira.plugin.system.customfieldtypes:userpicker" }, "status": { "name":"status", "type":"com.atlassian.jira.issue.status.Status", "value": { "self":"https://example.com/jira/rest/api/latest/status/5", "name":"Resolved" } }, ... }, "transitions":"https://example.com/jira/rest/api/latest/issue/XYZ-1234/transitions" } 

我不想使用Jira自己的客户端(我的应用程序中不需要太多依赖项)。

编辑:我问我的问题另一种方法,试图说清楚: 如何使用jax-rs将bean结构映射到不同的模式

您的带注释的类应该是双射的:它应该允许生成从中解组的相同输入。 如果您仍想使用非双射对象图,可以通过以下方式使用@XmlAnyElement

 public class Issue { @XmlElement(required = true) protected Fields fields; public Fields getFields() { return fields; } } 

在您提供的输入中,字段不是列表,而是字段(JSON使用[]来分隔列表):

 public class Fields { @XmlElement(required = true) protected Summary summary; @XmlAnyElement private List fields; public List getFields() { return fields; } public Summary getSummary() { return summary; } } 

为了捕获摘要,您必须定义一个专用类。 剩余字段将分组在元素的fields列表中。

 public class Summary { @XmlAttribute protected String name; public String getName() { return name; } } 

下面,使用您的输入进行unit testing表明一切正常:

 public class JaxbTest { @Test public void unmarshal() throws JAXBException, IOException { URL xmlUrl = Resources.getResource("json.txt"); InputStream stream = Resources.newInputStreamSupplier(xmlUrl).getInput(); Issue issue = parse(stream, Issue.class); assertEquals("summary", issue.getFields().getSummary().getName()); Element element = issue.getFields().getFields().get(0); assertEquals("customfield_10080", element.getTagName()); assertEquals("name", element.getFirstChild().getLocalName()); assertEquals("Testeur", element.getFirstChild().getFirstChild().getTextContent()); } private  T parse(InputStream stream, Class clazz) throws JAXBException { JSONUnmarshaller unmarshaller = JsonContextNatural().createJSONUnmarshaller(); return unmarshaller.unmarshalFromJSON(stream, clazz); } private JSONJAXBContext JsonContextNatural() throws JAXBException { return new JSONJAXBContext(JSONConfiguration.natural().build(), Issue.class); } } 

此测试表明,如果不使用专用类,您的代码很快就会难以阅读。

您将需要这些maven依赖项来运行它:

  junit junit 4.8.2 test   com.google.guava guava r08   com.sun.jersey jersey-json 1.6  
 { "expand":"html", "self":"xxx/jira/rest/api/latest/issue/EPC-2731";, "key":"EPC-2731", "fields":{ "summary":{ "name":"summary", "type":"java.lang.String", "value":"Fwd: commentaires vides dans FicheSousGroupement" }, "timetracking":{ "name":"timetracking", "type":"com.atlassian.jira.issue.fields.TimeTrackingSystemField", "value":{ "timeestimate":0, "timespent":60 } }, "issuetype":{ "name":"issuetype", "type":"com.atlassian.jira.issue.issuetype.IssueType", "value":{ "self":"xxx/jira/rest/api/latest/issueType/2";, "name":"Nouvelle fonctionnalité", "subtask":false } }, "customfield_10080":{ "name":"Testeur", "type":"com.atlassian.jira.plugin.system.customfieldtypes:userpicker" },