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;  
}

The code works until MessageBase msggg=gson.fromJson(data, MessageBase.class);. I get this exception:

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)

What I need to do? I put .jar in lib folder and i think the tomcat load the .jar well.

MikO
  • 18,243
  • 12
  • 77
  • 109
user1612863
  • 229
  • 1
  • 2
  • 5

6 Answers6

31

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.

MikO
  • 18,243
  • 12
  • 77
  • 109
8

I have same problem when use retrofit and figure out this is happen when use abstract class so i'm create empty class that extends abstract class (MessageBase) like this :

public class BaseResponse extends MessageBase {

}

And now use BaseResponse that have all field of MessageBase

Radesh
  • 13,084
  • 4
  • 51
  • 64
4

Abstract classes can’t be instantiated, only subclassed. Abstract method bodies must be empty (no curly braces). Remove the "abstract" from the public MessageBase and you are good to go.

See the Link Java Abstract Classes

Jay Patel
  • 89
  • 7
0

Make sure!

1- Class implements Serializable

2- Not to be abstract even child classes

3- Should be public

Ali Akram
  • 4,803
  • 3
  • 29
  • 38
0

Problem Example:

You have an abstract class which is composed of abstract classes members, then you extend this main class and its members too.

public abstract class Receipt implements Serializable {

    @Expose
    protected ReceiptMainDetails mainDetails;

    @Expose
    protected ReceiptDetails payerReceiptDetails;

    @Expose
    protected ReceiptDetails payeeReceiptDetails;

(The details are all abstract too)

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() {}

    }

(And the other details are extended too)

GSON will not be able to transform the json to the object.

Solution

The Receipt can be abstract, but its members must be concrete classes, even though you may extend them again.

Test your solution

@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);
}
0

Sometimes this happens if you accidentally put the object of the same class inside the same class, like this:

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

Check for Typos, maybe you had a class called StudentData and you just pressed enter during autocomplete.

Reejesh PK
  • 658
  • 1
  • 11
  • 27