Skip to content

@RestController returns {} with Gson when return value is interface with generic type #24234

@iwangjie

Description

@iwangjie

Affects: \ 4.2.5

I defined a method in Controller that returns a Page interface, but in fact I return a PageImpl implementation class object, but I receive a response value of {}

Postman Request result:
image

Controller RequestMapping:
image

Page:

public interface Page<T> {

    int getTotalPages();

    int getNumber();

    int getSize();

    int getNumberOfElements();

    List<T> getContent();

    boolean hasContent();

    boolean isFirst();

    boolean isLast();

    boolean hasNext();

    boolean hasPrevious();

    long getTotalElements();

}

PageImpl:

public class PageImpl<T> implements Page<T>,Serializable {
    private static final long serialVersionUID = 2693326466571693579L;
    private List<T> content = new ArrayList();
    private long total;
    private PageRequest pageable;

    public PageImpl(){

    }

    public PageImpl(List<T> content, PageRequest pageable, long total){
        this.content.addAll(content);
        this.pageable = pageable;
        this.total = !content.isEmpty() && pageable != null && (long)(pageable.getOffset() + pageable.getPageSize()) > total?(long)(pageable.getOffset() + content.size()):total;
    }


    @Override
    public int getTotalPages() {
        return this.getSize() == 0?1:(int)Math.ceil((double)this.total / (double)this.getSize());
    }

    @Override
    public int getNumber() {
        return this.pageable == null?0:this.pageable.getPageNumber();

    }

    @Override
    public int getSize() {
        return this.pageable == null?0:this.pageable.getPageSize();
    }

    @Override
    public int getNumberOfElements() {
        return this.content.size();
    }

    @Override
    public List getContent() {
        return Collections.unmodifiableList(this.content);    }

    @Override
    public boolean hasContent() {
        return !this.content.isEmpty();
    }

    @Override
    public boolean isFirst() {
        return !this.hasPrevious();
    }

    @Override
    public boolean isLast() {
        return !this.hasNext();
    }

    @Override
    public boolean hasNext() {
        return this.getNumber() + 1 < this.getTotalPages();
    }

    @Override
    public boolean hasPrevious() {
        return this.getNumber() > 0;
    }

    @Override
    public long getTotalElements() {
        return this.total;
    }
}

I tried analyzing the code and found that in the AbstractMessageConverterMethodProcessor class

image

The Type obtained here is the Type of the interface, not the Type of the implementation class. I analyzed the source code of Gson and found that Gson is a set of attributes obtained based on the byte code of the passed Type. The interface itself does not have any fields. The cause of this problem.

Metadata

Metadata

Assignees

Labels

in: webIssues in web modules (web, webmvc, webflux, websocket)status: duplicateA duplicate of another issue

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions