【问题标题】:JSONMappingException - cannot desierialize Java objectJSONMappingException - 无法反序列化 Java 对象
【发布时间】:2013-01-04 21:55:34
【问题描述】:

使用ObjectMapper 反序列化对象时出现以下错误:

JSONMappingException 无法构造实例 org.springframework.data.Page,问题:抽象类型只能是 用额外的类型信息实例化。

我正在尝试将 JSON 字符串序列化为 Spring 数据对象 org.springframework.data.Page,它表示 T 类型的页面。

User 类是一个简单的 POJO,具有 firstlast 名称。我反序列化的 JSON 字符串是:

{
    "content": [
        {
            "firstname": "John",
            "lastname": "Doe"
        },
        {
            "firstname": "Jane",
            "lastname": "Doe"
        }
    ],
    "size": 2,
    "number": 0,
    "sort": [
        {
            "direction": "DESC",
            "property": "timestamp",
            "ascending": false
        }
    ],
    "totalPages": 150,
    "numberOfElements": 100,
    "totalElements": 15000,
    "firstPage": true,
    "lastPage": false
}

这会导致异常:

Page<User> userPage = (Page<User>) new ObjectMapper().mapToJavaObject(json, new TypeReference<Page<User>>(){};

由于Page 是一个 Spring 对象,我无法修改它,我认为这与我在其他地方看到的这个问题的方式有点不同。有什么想法吗?

【问题讨论】:

  • 我用我提出的原始答案尝试了反序列化。但是 Page 实现具有无法从输入 JSON 反序列化的虚拟属性,并且会导致进程失败。最好的办法是编写一个自定义 bean 以将 JSON 反序列化为,然后使用来自该自定义 bean 的值实例化一个 PageImpl。

标签: java json jackson


【解决方案1】:

我最终使用了类似的东西,按照@Perception 的建议创建了一个 bean:

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

import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;

public class PageImplBean<T> extends PageImpl<T> {

    private static final long serialVersionUID = 1L;
    private int number;
    private int size;
    private int totalPages;
    private int numberOfElements;
    private long totalElements;
    private boolean previousPage;
    private boolean firstPage;
    private boolean nextPage;
    private boolean lastPage;
    private List<T> content;
    private Sort sort;

    public PageImplBean() {
        super(new ArrayList<T>());
    }

    public int getNumber() {
        return number;
    }

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

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public int getTotalPages() {
        return totalPages;
    }

    public void setTotalPages(int totalPages) {
        this.totalPages = totalPages;
    }

    public int getNumberOfElements() {
        return numberOfElements;
    }

    public void setNumberOfElements(int numberOfElements) {
        this.numberOfElements = numberOfElements;
    }

    public long getTotalElements() {
        return totalElements;
    }

    public void setTotalElements(long totalElements) {
        this.totalElements = totalElements;
    }

    public boolean isPreviousPage() {
        return previousPage;
    }

    public void setPreviousPage(boolean previousPage) {
        this.previousPage = previousPage;
    }

    public boolean isFirstPage() {
        return firstPage;
    }

    public void setFirstPage(boolean firstPage) {
        this.firstPage = firstPage;
    }

    public boolean isNextPage() {
        return nextPage;
    }

    public void setNextPage(boolean nextPage) {
        this.nextPage = nextPage;
    }

    public boolean isLastPage() {
        return lastPage;
    }

    public void setLastPage(boolean lastPage) {
        this.lastPage = lastPage;
    }

    public List<T> getContent() {
        return content;
    }

    public void setContent(List<T> content) {
        this.content = content;
    }

    public Sort getSort() {
        return sort;
    }

    public void setSort(Sort sort) {
        this.sort = sort;
    }

    public PageImpl<T> pageImpl() {
        return new PageImpl<T>(getContent(), new PageRequest(getNumber(),
                getSize(), getSort()), getTotalElements());
    }
}

然后修改您的代码以使用具体类并获取 PageImpl:

@SuppressWarnings("unchecked")
Page<User> userPage = ((PageImplBean<User>)new ObjectMapper().readValue(json, new TypeReference<PageImplBean<User>>() {})).pageImpl();

【讨论】:

  • 不错的答案!唯一缺少的是两个属性:lastPage 和 firstPage 应该分别重命名为 last 和 first。
【解决方案2】:

你可以这样做:

public class YourClass {

    static class CustomPage extends PageImpl<User> {

        @JsonCreator(mode = Mode.PROPERTIES)
        public CustomPage(@JsonProperty("content") List<User> content, @JsonProperty("number") int page, @JsonProperty("size") int size, @JsonProperty("totalElements") long total) {
            super(content, new PageRequest(page, size), total);
        }

    }

    public Page<User> makeRequest(String json) {

        Page<User> pg = new ObjectMapper().readValue(json, CustomPage.class);
        return pg;

    }

}    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-11
    • 2016-12-30
    • 2019-12-06
    • 1970-01-01
    • 2014-08-10
    • 2014-08-04
    • 2015-05-29
    相关资源
    最近更新 更多