Как сделать POJO и разобрать рекурсивные объекты с помощью jackson?

У меня есть ответ JSON ниже, который я получаю от службы отдыха. Теперь мне нужно десериализовать ниже ответ JSON в POJO. Я работаю с Джексоном.

{
    "pagination": {
        "number": 1,
        "entriesPerPage": 200,
        "total": 3
    },
    "postings": [{
        "categories": [{
        "taskid": "79720",
        "name": "Sunglasses",
        "parentCategory": {
            "taskid": "394",
            "name": "Sunglasses & Fashion Eyewear",
            "parentCategory": {
                "taskid": "2340",
                "name": "Men's Accessories",
                "parentCategory": {
                    "taskid": "10987",
                    "name": "Clothing, Shoes & Accessories"
                }
            }
        }
    }]
},
{
    "categories": [{
        "taskid": "12980",
        "name": "Toys",
        "parentCategory": {
            "taskid": "123",
            "name": "Fashion",
            "parentCategory": {
                "taskid": "78765",
                "name": "Men's Accessories"
            }
        }
    }]
}],
    "total": 2
}

В приведенном выше json postings — это массив JSON, который может иметь несколько объектов posting json. Теперь categories также является массивом JSON. Теперь сложная часть заключается в том, что я могу иметь несколько уровней parentCategory внутри каждого объекта категории, и я не знаю, сколько уровней parentCategory у меня будет. Приведите выше JSON, мне нужно извлечь taskid каждой категории и taskId последней parentCategory. Так должно быть так:

79720=10987
12980=78765

Где 79720 — это идентификатор задачи категории, а 10987 — идентификатор задачи последней parentCategory. Аналогично для другого.

Ниже приведен мой код, в котором я десериализую JSON в свой POJO, выполнив http-вызов:

ResponseEntity<Stuff> responseEntity = HttpClient.getInstance().getClient()
    .exchange(URI.create(endpoint), HttpMethod.POST, requestEntity, Stuff.class);
Stuff response = responseEntity.getBody();

List<Posting> postings = response.getPostings();
for(Posting postings : postings) {
    //....
}

У меня есть путаница - как сделать POJO для вышеуказанного JSON? Я попытался использовать jsonschema2pojo, но он не создает правильных классов для parentCategory. Поскольку у меня могут быть вложенные уровни parentCategory, о которых я не знаю заранее.

Возможно ли это сделать с помощью Джексона?

Это класс POJO, сгенерированный для Category и ParentCategory. Я не уверен, нужно ли мне вносить какие-либо изменения здесь, чтобы я мог анализировать рекурсивный объект parentCategory.

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({"taskid", "name", "parentCategory"})
public class Category {
  @JsonProperty("taskid")
  private String taskid;
  @JsonProperty("name")
  private String name;
  @JsonProperty("parentCategory")
  private ParentCategory parentCategory;
  @JsonIgnore
  private Map<String, Object> additionalProperties = new HashMap<String, Object>();

  ...

}

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({"taskid", "name", "parentCategory"})
public class ParentCategory {
  @JsonProperty("taskid")
  private String taskid;
  @JsonProperty("name")
  private String name;
  @JsonProperty("parentCategory")
  private ParentCategory parentCategory;
  @JsonIgnore
  private Map<String, Object> additionalProperties = new HashMap<String, Object>();

  ...

}

person user1950349    schedule 26.01.2018    source источник
comment
Проблема не в том, что объект глубоко вложен, проблема в том, что parentCategory рекурсивен. Найдите и прочитайте о рекурсивном подходе Джексона.   -  person PeterMmm    schedule 27.01.2018
comment
@PeterMmm Я видел эту статью, но не понимаю, как использовать JsonManagedReference или JsonBackReference в моем случае. Я обновил свой вопрос с помощью POjO, который у меня есть для объектов Category и ParentCategory.   -  person user1950349    schedule 27.01.2018
comment
Возможный дубликат анализа рекурсивного вложенного поля с использованием jackson   -  person Sharon Ben Asher    schedule 28.01.2018


Ответы (1)


На этот раз я бы использовал Gson.

Который управляет рекурсией с меньшими усилиями.

Pojos можно сделать с веб-сайта json2pojo, просто выбрав Gson в качестве библиотеки JSon.

Это Пожо:

import java.io.Serializable;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class Pagination implements Serializable
{

    public Pagination() {
        super();
        // TODO Auto-generated constructor stub
    }

    @SerializedName("number")
    @Expose
    private Integer number;
    @SerializedName("entriesPerPage")
    @Expose
    private Integer entriesPerPage;
    @SerializedName("total")
    @Expose
    private Integer total;
    private final static long serialVersionUID = 5114620434202813556L;

    public Integer getNumber() {
        return number;
    }

    public void setNumber(Integer number) {
        this.number = number;
    }

    public Integer getEntriesPerPage() {
        return entriesPerPage;
    }

    public void setEntriesPerPage(Integer entriesPerPage) {
        this.entriesPerPage = entriesPerPage;
    }

    public Integer getTotal() {
        return total;
    }

    public void setTotal(Integer total) {
        this.total = total;
    }

}



import java.io.Serializable;
import java.util.List;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class Categories implements Serializable
{

    public Categories() {
        super();
        // TODO Auto-generated constructor stub
    }

    @SerializedName("pagination")
    @Expose
    private Pagination pagination;
    @SerializedName("postings")
    @Expose
    private List<Posting> postings = null;
    @SerializedName("total")
    @Expose
    private Integer total;
    private final static long serialVersionUID = 4589512697836725240L;

    public Pagination getPagination() {
        return pagination;
    }

    public void setPagination(Pagination pagination) {
        this.pagination = pagination;
    }

    public List<Posting> getPostings() {
        return postings;
    }

    public void setPostings(List<Posting> postings) {
        this.postings = postings;
    }

    public Integer getTotal() {
        return total;
    }

    public void setTotal(Integer total) {
        this.total = total;
    }

}


import java.io.Serializable;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class Category implements Serializable
{

    public Category() {
        super();
        // TODO Auto-generated constructor stub
    }

    @SerializedName("taskid")
    @Expose
    private String taskid;
    @SerializedName("name")
    @Expose
    private String name;
    @SerializedName("parentCategory")
    @Expose
    private ParentCategory parentCategory;
    private final static long serialVersionUID = -2127963072268572959L;

    public String getTaskid() {
        return taskid;
    }

    public void setTaskid(String taskid) {
        this.taskid = taskid;
    }

    public String getName() {
        return name;
    }

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

    public ParentCategory getParentCategory() {
        return parentCategory;
    }

    public void setParentCategory(ParentCategory parentCategory) {
        this.parentCategory = parentCategory;
    }

}


import java.io.Serializable;
import java.util.List;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class Posting implements Serializable
{

    @SerializedName("categories")
    @Expose
    private List<Category> categories = null;
    private final static long serialVersionUID = 8135185675909461065L;

    public List<Category> getCategories() {
        return categories;
    }

    public Posting() {
        super();
        // TODO Auto-generated constructor stub
    }

    public void setCategories(List<Category> categories) {
        this.categories = categories;
    }

}


import java.io.Serializable;
import java.util.List;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class ParentCategory implements Serializable
{

    @SerializedName("taskid")
    @Expose
    private String taskid;
    @SerializedName("name")
    @Expose
    private String name;
    @SerializedName("parentCategory")
    @Expose
    private List<ParentCategory>  parentCategory;


    public ParentCategory() {
        super();
        // TODO Auto-generated constructor stub
    }

    private final static long serialVersionUID = -5989749742502713615L;

    public String getTaskid() {
        return taskid;
    }

    public void setTaskid(String taskid) {
        this.taskid = taskid;
    }

    public String getName() {
        return name;
    }

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

    public List<ParentCategory> getParentCategory() {
        return parentCategory;
    }

    public void setParentCategory(List<ParentCategory> parentCategory) {
        this.parentCategory = parentCategory;
    }

}

Итак, это тестовая реализация:

 Pagination pagination = new Pagination();

         pagination.setNumber(1);
         pagination.setEntriesPerPage(200);
         pagination.setTotal(3);

         Categories categories = new Categories(); 
         categories.setPagination(pagination);

         Category category = new Category();
         category.setName("Sunglasses");
         category.setTaskid("79720");

         List<Category> categoryList = new ArrayList<Category>();

         Posting posting = new Posting(); 
         posting.setCategories(categoryList);

         List<ParentCategory> parentCategoryList = new ArrayList<ParentCategory>();
         List<ParentCategory> parentCategoryList2 = new ArrayList<ParentCategory>();

         ParentCategory  parentCategory1 = new ParentCategory(); 
         parentCategory1.setName("Sunglasses & Fashion Eyewear");
         parentCategory1.setTaskid("394");

         ParentCategory  parentCategory2 = new ParentCategory(); 
         parentCategory2.setName("Men's Accessories");
         parentCategory2.setTaskid("2340");

         ParentCategory  parentCategory3 = new ParentCategory(); 
         parentCategory3.setName("Clothing, Shoes & Accessories");
         parentCategory3.setTaskid("10987");

         parentCategoryList.add(parentCategory2); 
         parentCategoryList2.add(parentCategory3);
          parentCategory2.setParentCategory(parentCategoryList2);
         parentCategory1.setParentCategory(parentCategoryList);
         category.setParentCategory(parentCategory1);

          Gson gson = new Gson();
            System.out.println(gson.toJson(category));

... и это результат Json:

{
    "taskid": "79720",
    "name": "Sunglasses",
    "parentCategory": {
        "taskid": "394",
        "name": "Sunglasses \u0026 Fashion Eyewear",
        "parentCategory": [{
            "taskid": "2340",
            "name": "Men\u0027s Accessories",
            "parentCategory": [{
                "taskid": "10987",
                "name": "Clothing, Shoes \u0026 Accessories"
            }]
        }]
    }
}

Возможно, все еще нужно немного настроить, но вы поняли идею.

Надеюсь, поможет!

РЕДАКТИРОВАТЬ: по запросу оператора я добавляю версию Джексона.

Пожо:

import java.io.Serializable;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({"taskid", "name", "parentCategory"})
public class ParentCategory implements Serializable{
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    @JsonProperty("taskid")
    private String taskid;
    @JsonProperty("name")
    private String name;
    @JsonProperty("parentCategory")
    private ParentCategory parentCategory;
    public String getTaskid() {
        return taskid;
    }
    public void setTaskid(String taskid) {
        this.taskid = taskid;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public ParentCategory getParentCategory() {
        return parentCategory;
    }
    public void setParentCategory(ParentCategory parentCategory) {
        this.parentCategory = parentCategory;
    }


}


import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({"taskid", "name", "parentCategory"})
public class Category implements Serializable{
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    @JsonProperty("taskid")
    private String taskid;
    @JsonProperty("name")
    private String name;
    @JsonProperty("parentCategory")
    private ParentCategory parentCategory;

    public String getTaskid() {
        return taskid;
    }
    public void setTaskid(String taskid) {
        this.taskid = taskid;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public ParentCategory getParentCategory() {
        return parentCategory;
    }
    public void setParentCategory(ParentCategory parentCategory) {
        this.parentCategory = parentCategory;
    }



}


public class Test {


    public static void main(String[] args) throws JsonProcessingException {


         Category category = new Category();
         category.setName("Sunglasses");
         category.setTaskid("79720");

         List<Category> categoryList = new ArrayList<Category>();

         List<ParentCategory> parentCategoryList = new ArrayList<ParentCategory>();
         List<ParentCategory> parentCategoryList2 = new ArrayList<ParentCategory>();

         ParentCategory  parentCategory1 = new ParentCategory(); 
         parentCategory1.setName("Sunglasses & Fashion Eyewear");
         parentCategory1.setTaskid("394");

         ParentCategory  parentCategory2 = new ParentCategory(); 
         parentCategory2.setName("Men's Accessories");
         parentCategory2.setTaskid("2340");

         ParentCategory  parentCategory3 = new ParentCategory(); 
         parentCategory3.setName("Clothing, Shoes & Accessories");
         parentCategory3.setTaskid("10987");

         parentCategory1.setParentCategory(parentCategory2);
         parentCategory2.setParentCategory(parentCategory3);
         category.setParentCategory(parentCategory1);

        ObjectMapper objectMapper = new ObjectMapper();

        String testJson = objectMapper.writeValueAsString(category);
        System.out.println(testJson);
    }

}

И вот снова результат теста:

{
    "taskid": "79720",
    "name": "Sunglasses",
    "parentCategory": {
        "taskid": "394",
        "name": "Sunglasses & Fashion Eyewear",
        "parentCategory": {
            "taskid": "2340",
            "name": "Men's Accessories",
            "parentCategory": {
                "taskid": "10987",
                "name": "Clothing, Shoes & Accessories"
            }
        }
    }
}
person Black.Jack    schedule 26.01.2018
comment
Спасибо за работу с Gson. Может ли это не работать с Джексоном? Какие-нибудь мысли? - person user1950349; 27.01.2018
comment
комментарии показали вам страницы документации о реализации Джексона. Нет других альтернатив, кроме этого, или переключиться на реализацию Джерси (поскольку я полагаю, что вы с RestEasy), которая может хорошо интегрировать Gson в качестве синтаксического анализатора. - person Black.Jack; 27.01.2018
comment
Я видел эту страницу документа для реализации Джексона и, похоже, не могу десериализовать json в свой Pojo с помощью JsonManagedReference и JsonBackReference. Не уверен, что я делаю неправильно. - person user1950349; 27.01.2018
comment
Добавлена ​​версия Джексона. - person Black.Jack; 27.01.2018
comment
Я думаю, вы вставляете список, но у вас нет списка в вашем джексонском POJO для parentCategory, поэтому не уверен, что он работает. - person user1950349; 27.01.2018
comment
Давайте продолжим обсуждение в чате. - person user1950349; 27.01.2018
comment
Я пытаюсь преобразовать тот же JSON в POJO. Как я могу извлечь последний идентификатор последнего уровня parentCategory? - person user1950349; 27.01.2018