как использовать некоторую косвенность при демаршаллинге JSON к Java-бину, используя Джерси, используя аннотации Jaxb - PullRequest
5 голосов
/ 28 апреля 2011

Я пытаюсь разобрать все полученные файлы json (из спокойного веб-сервиса Jira).

Проблема заключается в том, что «проблема» имеет свойство «сводка» и список полей.

Сводка отсутствует в качестве атрибута в полученном json, но в качестве значения параметра «»поля "атрибут.Я настаиваю на демаршаллинге этой структуры:

@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 (слишком много зависимостей, которые мне не нужны вмое приложение).

edit: я задал свой вопрос другим способом, чтобы попытаться прояснить: как отобразить структуру bean-компонента в другую схему с помощью jax-rs

Ответы [ 2 ]

3 голосов
/ 03 мая 2011

Ваш аннотированный класс должен быть биективным: он должен позволять генерировать тот же вход, из которого он был демаршалирован. Если вы все еще хотите использовать небиективный граф объектов, вы можете использовать @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<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>
0 голосов
/ 20 мая 2011
{
    "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" 
            },
...