Как десериализовать массив JSON?

Я использую Jackson в CXF для сериализации/десериализации данных. К сожалению, у меня возникли трудности с настройкой CXF/Jackson для десериализации массива JSON. Буду признателен за помощь в решении вопроса.

До этого момента большая часть данных json была в объектном формате, т.е.

{ "objectCollection": [ {...}, {...}, {...}... ] }

Однако рассматриваемые данные json имеют форму:

[ {...}, {...}, {...} ]

Конечная точка веб-службы ожидает объект «GroupsDto» (см. далее), который имеет одно свойство — набор групп, который передается через массив JSON.

@PATH(...)
public Response createGroups(GroupsDto groups) {
...
}

Я добавил @JsonDeserialize в свойство коллекции GroupsDto следующим образом, но это НЕ работает. Я продолжаю получать: «Не удается десериализовать экземпляр GroupsDto из токена START_ARRAY».

public class GroupsDto {

       private Collection<GroupDto> groups;

       /**
        * @return the groups
        */
       @XmlElement(name="group")
       @JsonDeserialize(contentAs=GroupDto.class)
       public Collection<GroupDto> getGroups() {
               return groups;
       }
...
}

person Ari    schedule 19.06.2012    source источник
comment
Проверьте этот вопрос [Джексон - чтение массива JSON с помощью Robospice с использованием метода loadDataFromNetwork()][1] [1]: stackoverflow.com/questions/18792702/   -  person Sneg    schedule 16.05.2014


Ответы (2)


Если данные json имеют форму:

[ {...}, {...}, {...} ]

Вы должны использовать добавить еще один класс, скажем, «оболочку»:

@JsonIgnoreProperties(ignoreUnknown = true)
public class ListDto extends ArrayList<GroupDto> {

    public ListDto() {
    }
}

И используйте этот класс во время спуска. Этот подход работал для меня.

person Snehal Masne    schedule 19.09.2014

Вам просто нужно указать @JsonDeserialize(contentAs=GroupDto.class) в вашем установщике. Сериализация всегда на get, десериализация всегда на set, или, если вы предпочитаете, вы можете указать в поле и то, и другое.

Документация по Сериализация и Десериализация

Пример кода:

import java.io.IOException;
import java.util.List;

import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.annotate.JsonDeserialize;

public class JacksonDeserialize {

    public static class ModelClass {

        private String name;

        public ModelClass() {
        }

        public String getName() {
            return name;
        }

        public void setName(final String name) {
            this.name = name;
        }

        public ModelClass(final String name) {
            super();
            this.name = name;
        }

        @Override
        public String toString() {
            return "ModelClass [name=" + name + "]";
        }

    }

    public static class ListModelClass {

        private List<ModelClass> list;

        @JsonDeserialize(contentAs = ModelClass.class)
        public void setList(final List<ModelClass> list) {
            this.list = list;
        }

        @Override
        public String toString() {
            return "ListModelClass [list=" + list + "]";
        }

    }

    public static void main(final String[] args) throws JsonGenerationException, JsonMappingException, IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        System.out.println(objectMapper.readValue("{\"list\":[{\"name\":\"name1\"},{\"name\":\"name2\"}]}",
                ListModelClass.class));
    }

}
person Francisco Spaeth    schedule 19.06.2012
comment
Спасибо за предупреждение о проблеме с геттером/сеттером. Я заметил в вашем примере, что вы квалифицируете массив json, т.е. {\ list \:...} Можно ли десериализовать без квалификации? Если да, то как? - person Ari; 20.06.2012
comment
квалификации нет, в этом случае магия творится с помощью аннотации @JsonDeserialize. Свойство contentAs должно указывать, что это коллекция и будет десериализовано как ModelClass. Если вы хотите, вы можете изменить имя свойства с list на другое. Название не имеет значения, важна аннотация. - person Francisco Spaeth; 20.06.2012
comment
Я понимаю, что конкретное имя не имеет значения, но что делать в случае, когда имени нет? В вашем примере вы читаете в {"list": [...]}, у которого есть ключ «список», но что, если ключа (имени) нет, то есть [...]? - person Ari; 20.06.2012
comment
Ах, вот в чем проблема. Сериализация/десериализация обрабатывается CXF, который вызывает предопределенный ObjectMapper; следовательно, я не могу просто передать TypeReference пользовательскому ObjectMapper, я должен полагаться на предопределенные ObjectMapper и аннотации. - person Ari; 20.06.2012
comment
Хорошо, какую библиотеку вы используете для интеграции обоих? - person Francisco Spaeth; 20.06.2012
comment
Нет библиотеки интеграции; CXF позволяет указать предопределенный обработчик. - person Ari; 21.06.2012