java - 在使用 jaxb 注释使用 Jersey 将 json 解码为 java bean 时如何使用一些间接寻址

标签 java json rest jersey unmarshalling

我正在尝试解码一些收到的 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/

相关文章:

java - 在角度站点中使用 xpath 时找不到元素

json - 如何使用 jq 从 terraform 状态文件中提取特定字段?

java - Spring Boot PostMapping 反序列化长数组

java - 如何使用android studio在java中获取这个数组的每个元素

java - Jersey:处理 Restful HTTP PUT(更新)请求的最佳实践

java - Jersey 休息客户端不添加查询参数

java - 如何对 Jersey 的用户进行身份验证

java - 如何将 JUnitPerf 与 JWebUnit 和 JUnit 4 一起使用?

java - 在不同的计算机上出现此错误 : The origin server did not find a current representation for the

java - 如何在Java中运行tshark来实时获取数据包?