我正在尝试解码一些收到的 json(来自 Jira restful web 服务)。
问题是:一个“issue”有一个“summary”属性和一个字段列表。
摘要不作为接收到的 json 中的属性存在,而是作为“fields”属性的值存在。我坚持解码为这种结构:
@XmlRootElement
class Issue {
String summary;
List<Field> 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 自己的客户端(我不想在我的应用程序中使用太多依赖项)。
编辑:我用另一种方式问了我的问题,试图弄清楚:how to map a bean structure to a different schema with jax-rs
最佳答案
您的注释类应该是双射的:它应该允许生成与解码时相同的输入。如果您仍想使用非双射对象图,可以按以下方式使用 @XmlAnyElement
:
public class Issue {
@XmlElement(required = true)
protected Fields fields;
public Fields getFields() {
return fields;
}
}
在你给的输入中,fields不是一个列表,而是一个字段(JSON使用[]分隔列表):
public class Fields {
@XmlElement(required = true)
protected Summary summary;
@XmlAnyElement
private List<Element> fields;
public List<Element> getFields() {
return fields;
}
public Summary getSummary() {
return summary;
}
}
为了捕获摘要,您必须定义一个专用类。其余字段将分组在 fields
元素列表中。
public class Summary {
@XmlAttribute
protected String name;
public String getName() {
return name;
}
}
下面,使用您的输入进行的单元测试显示一切正常:
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> T parse(InputStream stream, Class<T> 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 依赖项来运行它:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>r08</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>1.6</version>
</dependency>
关于java - 在使用 jaxb 注释使用 Jersey 将 json 解码为 java bean 时如何使用一些间接寻址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5820028/