简体   繁体   English

为什么Google Gson.toJson会丢失数据

[英]Why Google Gson.toJson loses data

I have five classes: 我有五个班:

Comment , Paper , WoundPaper , Document , WoundDoc . CommentPaperWoundPaper PaperDocumentWoundDoc

Comment is a holder for text. Comment是文本的持有者。
Paper is empty and abstract class. Paper是空的抽象类。
WoundPaper extends Paper and stores a String and an ArrayList of Comments . WoundPaper扩展Paper并存储String和Comments
Document is abstract class and stores ArrayList of <? extends Paper> Document是抽象类,存储<? extends Paper> <? extends Paper> . <? extends Paper>
WoundDoc extends Document . WoundDoc扩展了Document

You can see those classes below: 您可以在下面看到这些类:

Comment class: 评论类:

public class Comment {

    private final String text;

    public static class Builder {
        private final String text;

        public Builder(String text) {
            this.text = text;
        }

        public Comment build(){
            return new Comment(this);
        }

    }

    private Comment(Builder builder) {
        this.text = builder.text;
    }

    public String getText() {
        return text;
    }

}

Paper class: 论文课:

public abstract class Paper {

    protected Paper(ArrayList<Comment> commentList) {
    }

}

WoundPaper class: WoundPaper类:

public class WoundPaper extends Paper {

    private final String imageUri;
    private final ArrayList<Comment> commentList;

    public static class Builder {
        private final String imageUri;
        private final ArrayList<Comment> commentList;

        public Builder(String imageUri, ArrayList<Comment> commentList) {
            this.imageUri = imageUri;
            this.commentList = commentList;
        }

        public WoundPaper build() {
            return new WoundPaper(this);
        }

    }

    private WoundPaper(Builder builder) {
        super(builder.commentList);
        this.imageUri = builder.imageUri;
        this.commentList = builder.commentList;
    }

}

Document class: 文件类:

public abstract class Document {
    private final ArrayList<? extends Paper> paperList;


    protected Document(ArrayList<? extends Paper> paperList) {
        this.paperList = paperList;
    }

}

WoundDoc class: WoundDoc类:

public class WoundDoc extends Document {

    public static class Builder {
        private final ArrayList<WoundPaper> paperList;

        public Builder(ArrayList<WoundPaper> paperList) {
            this.paperList = paperList;
        }

        public WoundDoc build() {
            return new WoundDoc(this);
        }

    }

    private WoundDoc(Builder builder) {
        super(builder.paperList);
    }

}

Now I have to create an instance of WoundDoc and convert it to JSON string by Gson.This is a sample code to do that: 现在我必须创建一个WoundDoc实例并通过Gson将其转换为JSON字符串。这是一个示例代码:

        Comment comment = new Comment.Builder("comment").build();
        ArrayList<Comment> commentList = new ArrayList<Comment>();
        commentList.add(comment);
        commentList.add(comment);

        WoundPaper woundPaper = new WoundPaper.Builder("some Uri", commentList).build();
        ArrayList<WoundPaper> woundPaperList = new ArrayList<WoundPaper>();
        woundPaperList.add(woundPaper);
        woundPaperList.add(woundPaper);

        WoundDoc woundDoc = new WoundDoc.Builder(woundPaperList).build();

        System.out.println("woundDoc to JSON >> " + gson.toJson(woundDoc));

But output is strange: 但输出很奇怪:

woundDoc to JSON >> {"paperList":[{},{}]} woundDoc to JSON >> {“paperList”:[{},{}]}

As I displayed before, WoundDoc stores list of WoundPaper and each WoundPaper stores list of comment s.But why there is no comment in output? 正如我之前显示的那样, WoundDoc存储了WoundPaper列表,每个WoundPaper存储了comment列表。但是为什么输出中没有comment

When gson goes to serialise the WoundDoc all it can tell is that there is a List of two objects of type something which extends Paper ( List<? extends Paper> ); 当gson去序列化WoundDoc它可以告诉我有一个List的两个类型的对象扩展PaperList<? extends Paper> ); the specific type is unknown. 具体类型未知。 As Paper has no fields for gson to work with it can only say that there are two entries within that list, but as they are the type Paper , which has no fields, there is no way to work out how to serialize those objects. 由于Paper没有gson可以使用的字段,因此只能说该列表中有两个条目,但由于它们是Paper类型,没有字段,因此无法确定如何序列化这些对象。

A way to resolve this is to pass type from your implementations to the abstract classes so that when gson inspects them it can see which class the objects it encounters are instances of, and so work out how to serialise them. 解决这个问题的一种方法是将类型从您的实现传递给抽象类,这样当gson检查它们时,它可以看到它遇到的对象是哪个类的实例,因此可以确定如何序列化它们。

Update Document to take a type parameter: 更新文档以获取类型参数:

public abstract class Document<T extends Paper> {
    private final ArrayList<T> paperList;


    protected Document(ArrayList<T> paperList) {
        this.paperList = paperList;
    }
}

Update WoundDoc to pass type to Document: 更新WoundDoc以将类型传递给Document:

public class WoundDoc extends Document<WoundPaper> {

Another way to resolve it if you are unable to make the above changes would be to write a custom serializer for WoundDoc 如果您无法进行上述更改,另一种解决方法是为WoundDoc编写自定义序列化WoundDoc

Personally I'd use the first solution and pass type, because I'm lazy and writing a custom serializer is more effort 我个人会使用第一个解决方案和传递类型,因为我很懒,编写自定义序列化器更省力

edit: Minor shout out to jackson which will throw an exception if you try to serialise something and it cannot work out how to do it. 编辑:轻微喊出杰克逊 ,如果你尝试序列化一些东西会抛出异常,但它无法解决如何做到这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM