Джексон десериализует внутреннюю коллекцию - PullRequest
1 голос
/ 21 марта 2019

У меня проблема с десериализацией внутренней коллекции: Представьте, что есть два класса:

// RootClass.java
package somepackage;

import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import java.util.ArrayList;
import java.util.List;

class RootClass {
    public List getItems() {
        return items;
    }

    public void setItems(List items) {
        this.items = items;
    }

    @JsonSerialize(contentAs = Item.class)
    List<Item> items = new ArrayList<>();
}

//Item.java
package somepackage;

class Item {
    String name;

    public Item() {
    }

    public String getName() {
        return name;
    }

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

    public Item(String cat) {
        name = cat;
    }
}

// main class
package somepackage;

import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;

public class SampleCase {
    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        RootClass root = new RootClass();
        root.items.add(new Item("cat"));
        String json = mapper.writeValueAsString(root);
        RootClass root2 = mapper.readValue(json, RootClass.class);
        Item item = (Item) root2.items.get(0);
    }
}

Я получаю исключение:

Exception in thread "main" java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class somepackage.Item (java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; somepackage.Item is in unnamed module of loader 'app')

Согласно javadoc @JsonSerialize(contentAs = Item.class) на коллекции помогло бы мне, но это не помогло бы. Вопрос: чего мне не хватает?

Если речь идет не об этой аннотации, я подозреваю, что существует стандартный способ решения проблемы (я не хочу создавать собственные десериализаторы).

Большинство вопросов по десериализации коллекций касаются ситуации, когда корневым объектом является сама коллекция, но для меня это не так.

Джексон 2.9.8 Java 11.0.2 OpenJDK x64

1 Ответ

3 голосов
/ 22 марта 2019

Нет ничего плохого в базовой форме вашего кода. То, что вы пытаетесь сделать, сработает. У вас просто есть проблемы с вашим кодом, начиная с того факта, что он даже не будет компилироваться, поскольку вы вызываете конструктор для Item, который принимает строку, и все же вы не определяете такой конструктор. Для работы с Джексоном также нужны геттеры.

Вот версия вашего кода, которая работает:

class RootClass {
    List<Item> items = new ArrayList<>();
    public List<Item> getItems() {
        return items;
    }
}

class Item {
    String name;
    Item() {}
    Item(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}

public static void main(String[] argsx) throws IOException{

    ObjectMapper mapper = new ObjectMapper();
    RootClass root = new RootClass();
    root.items.add(new Item("cat"));
    RootClass root2 = null;
    String json = mapper.writeValueAsString(root);
    root2 = mapper.readValue(json, RootClass.class);
    Item item = root2.items.get(0);
    System.out.println(item.getName());
}

Выход:

cat
...