23
protected void doPost(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException {

  System.out.println(request.getParameter("msg").toString());
  String data = request.getParameter("msg").toString();
  Gson gson = new Gson();
  MessageBase msggg = gson.fromJson(data, MessageBase.class);
  //System.out.println(msggg.Id + msggg.MessageText);
}

public abstract class MessageBase implements Serializable {
  public int Id;
  public String MessageText;
  public Date ReceiveDate;
}

public class SyncSmsMessage extends MessageBase {
  public String SenderNum;  
}

该代码有效,直到MessageBase msggg=gson.fromJson(data, MessageBase.class);. 我得到这个例外:

java.lang.RuntimeException: Failed to invoke public com.example.syncapp.MessageBase() with no args
  at com.google.gson.internal.ConstructorConstructor$2.construct(ConstructorConstructor.java:94)
  at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:162)
  at com.google.gson.Gson.fromJson(Gson.java:795)
  at com.google.gson.Gson.fromJson(Gson.java:761)
  at com.google.gson.Gson.fromJson(Gson.java:710)
  at com.google.gson.Gson.fromJson(Gson.java:682)
  at AndroidServlet.doPost(AndroidServlet.java:75)
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)

我需要做什么?我将 .jar 放在 lib 文件夹中,我认为 tomcat 可以很好地加载 .jar。

4

6 回答 6

30

From GSON User Guide:

While deserializing an Object, Gson needs to create a default instance of the class [...] Well-behaved classes that are meant for serialization and deserialization should have a no-argument constructor

Your problem is that GSON's Instance Creator needs a no-argument constructor in the class in which you want to deserialize the JSON response, namely MessageBase.

Otherwise, you need to write your own Instance Creator, like this.

于 2013-04-20T20:05:46.543 回答
8

我在使用改造时遇到了同样的问题,并发现在使用抽象类时会发生这种情况,所以我创建了一个扩展 抽象类(MessageBase)的空类,如下所示:

public class BaseResponse extends MessageBase {

}

现在使用BaseResponse具有所有领域的MessageBase

于 2018-11-21T08:14:56.483 回答
4

抽象类不能被实例化,只能被子类化。抽象方法主体必须为空(无花括号)。从公共 MessageBase 中删除“抽象”,你就可以开始了。

请参阅链接Java 抽象类

于 2019-07-08T07:15:28.883 回答
0

确保!

1-类implements Serializable

2-即使是子类也不抽象

3-应该是公开的

于 2021-01-27T07:14:39.517 回答
0

有时,如果您不小心将同一类的对象放在同一类中,就会发生这种情况,如下所示:

class Student{
val data:Student = Student() //this is the mistake  , remove it
}

检查错别字,也许你有一个名为 StudentData 的类,而你只是在自动完成过程中按了 Enter。

于 2022-03-04T17:42:02.397 回答
0

问题示例:

您有一个由抽象类成员组成的抽象类,然后您也扩展了这个主类及其成员。

public abstract class Receipt implements Serializable {

    @Expose
    protected ReceiptMainDetails mainDetails;

    @Expose
    protected ReceiptDetails payerReceiptDetails;

    @Expose
    protected ReceiptDetails payeeReceiptDetails;

(细节也很抽象)

public class TransferReceipt extends Receipt {

    public TransferReceipt() {}

    public TransferReceipt(TransferDetails body, Payer payer, Payee payee) {
        super(body, payer, payee);
    }

    public  static class TransferDetails extends ReceiptMainDetails {

        public TransferDetails() {}

    }

(并且其他细节也被扩展)

GSON 将无法将 json 转换为对象。

解决方案

Receipt 可以是抽象的,但它的成员必须是具体的类,即使您可以再次扩展它们。

测试您的解决方案

@Test
public void testGson() {

    String jsonString = "{youChooseWhatIsHere}";

    Gson gson = new Gson();

    TransferReceipt receipt = gson.fromJson(jsonString, TransferReceipt.class);

    String actualReceiptJson = gson.toJson(receipt);

    System.out.println(jsonString);
    System.out.println(actualReceiptJson);
    System.out.println(receipt);
}
于 2021-08-26T16:23:22.683 回答