如何使用jaxb注释使用Jersey将json解组为java bean时使用一些间接 [英] how to use some indirection when unmarshalling json to java bean using Jersey using jaxb annotations

查看:151
本文介绍了如何使用jaxb注释使用Jersey将json解组为java bean时使用一些间接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to unmarshall some received json (from Jira restful web service).

问题是:问题有一个摘要属性和一个字段列表。

Problem is: an "issue" has a "summary" property and a list of fields.

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

Summary is not present as an attribute in the received json, but as a value of the "fields" attribute. I insist on unmarshalling to this structure:

@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自己的客户端(我的应用程序中不需要太多依赖项) 。

I don't want to use Jira's own client (too many dependencies which I don't want in my app).

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

edit: I asked my question another way to try to make it clear: how to map a bean structure to a different schema with jax-rs

推荐答案

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

Your annotated class should be bijective: it should allow to generate the same input from which it was unmarshalled. If you still want to use a non-bijective object graph, you can use @XmlAnyElement the following way:

public class Issue {

    @XmlElement(required = true)
    protected Fields fields;

    public Fields getFields() {
        return fields;
    }
}

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

In the input you gave, fields is not a list, but a field (JSON uses [] to delimit lists):

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;
    }
}

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

In order to catch Summary, you'll have to define a dedicated class. Remaining fields will be grouped in the fields list of elements.

public class Summary {

    @XmlAttribute
    protected String name;

    public String getName() {
        return name;
    }
}

下面,使用您输入的单元测试显示一切work:

Below, a unit test using your input shows that everything work:

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);
    }
}

此测试显示不使用专用类,代码很快就会难以阅读。

This tests shows that without using dedicated classes, your code will quickly be hard to read.

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

You will need those maven dependencies to run it:

<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>

这篇关于如何使用jaxb注释使用Jersey将json解组为java bean时使用一些间接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆