Is Default No-Args Constructor Mandatory for Gson

Is default no-args constructor mandatory for Gson?

As of Gson 2.3.1.

Regardless of what the Gson documentation says, if your class doesn't have an no-args constructor and you have not registered any InstanceCreater objects, then it will create an ObjectConstructor (which constructs your Object) with an UnsafeAllocator which uses Reflection to get the allocateInstance method of the class sun.misc.Unsafe to create your class' instance.

This Unsafe class goes around the lack of no-args constructor and has many other dangerous uses. allocateInstance states

Allocate an instance but do not run any constructor. Initializes the
class if it has not yet been.

So it doesn't actually need a constructor and will go around your two argument constructor. See some examples here.

If you do have a no-args constructor, Gson will use an ObjectConstructor which uses that default Constructor by calling

yourClassType.getDeclaredConstructor(); // ie. empty, no-args

My 2 cents: Follow what Gson says and create your classes with a no-arg constructor or register an InstanceCreator. You might find yourself in a bad position using Unsafe.

Is it mandatory to keep a default constructor on classes handled by Gson?

Option 1: Yes, unless you create your own JsonDeserializer and JsonSerializer, in which case, your serializers can use whatever constructor you want.

Specifically, I would advise you to do the extra bit of work if you have other requirements in your classes, such as them being immutable, or if you want to guarantee a minimum state after initialization.

PS: actually, I supose the JsonDeserializer is enough. Insights anyone?

Option 2: (see Eugen's answer) consider using Genson instead

Option 3: (see Robertiano's answer) keep the default deserializers and implement InstanceCreator instead

Does Google's GSON use constructors?

Libraries like GSON, Jackson or the Java Persistence API (JPA) generally use a no-argument (default) construtor to instantiate an object and set its fields via reflection. In newer versions of GSON, you do not even have to declare a default constructor anymore, see here.

If you have to call a specific constructor in GSON, you can implement a custom JsonDeserializer, like already mentioned here.

In other libraries like Jackson, you can define the deserialization on methods, instead of fields (like GSON does), which allows you to substitute the missing specialized constructor call.

gson -- No-args constructor for class xyz with arrays

Try making your constructor public, so that gson can actually access it.

public License() {
this.computername = "";
this.date = "";
this.name = "";
this.prog = "";
// no-args constructor
}

but since Java creates a default constructor, you could just use:

public class License {
public String prog = "";
public String name = "";
public String computername = "";
public String date = "";
}

Update:

It's really quite trivial: JSONObject expects a Json object "{..}". You should use JSONArray which expects "[...]".

I tried it and it works. You should still change License class as noted above.

No-args constructor for class YYYY : does not exist. Register an InstanceCreator with Gson for this type to fix this problem

Answer to latest version of question:

import java.util.Arrays;

import com.google.gson.Gson;

public class Foo
{
public static void main(String[] args) throws Exception
{
new getElements().getEl();
}
}

class CategoriumContainer
{
Categorium categorium;

@Override
public String toString()
{
return String.format("{CategoriumContainer: categorium=%s}", categorium);
}
}

class Categorium
{
public String created_at;
public String c1;
public String updated_at;
public int id;

@Override
public String toString()
{
return String.format("{%s, %s, %s, %s}", created_at, c1, updated_at, id);
}
}

class getElements
{
String[] getEl() throws Exception
{
String stringa = "[{\"categorium\":{\"created_at\":\"2011-06-09T08:57:41Z\",\"c1\":\"rete stradale\",\"updated_at\":\"2011-06-09T08:57:41Z\",\"id\":1}}, {\"categorium\":{\"created_at\":\"2011-06-09T13:50:29Z\",\"c1\":\"servizi pubblici\",\"updated_at\":\"2011-06-09T13:50:29Z\",\"id\":2}}, {\"categorium\":{\"created_at\":\"2011-06-09T13:50:37Z\",\"c1\":\"illuminazione\",\"updated_at\":\"2011-06-09T13:50:37Z\",\"id\":3}}, {\"categorium\":{\"created_at\":\"2011-06-09T13:50:46Z\",\"c1\":\"inquinamento\",\"updated_at\":\"2011-06-09T13:50:46Z\",\"id\":4}}, {\"categorium\":{\"created_at\":\"2011-06-09T13:50:54Z\",\"c1\":\"vandalismo\",\"updated_at\":\"2011-06-09T13:50:54Z\",\"id\":5}}, {\"categorium\":{\"created_at\":\"2011-06-09T13:51:00Z\",\"c1\":\"abbandono\",\"updated_at\":\"2011-06-09T13:51:00Z\",\"id\":6}}, {\"categorium\":{\"created_at\":\"2011-06-15T08:33:17Z\",\"c1\":\"altro\",\"updated_at\":\"2011-06-15T08:33:17Z\",\"id\":8}}]";

Gson json = new Gson();
CategoriumContainer[] results = json.fromJson(stringa, CategoriumContainer[].class);
System.out.println(Arrays.toString(results));
// output:
// [{CategoriumContainer: categorium={2011-06-09T08:57:41Z, rete stradale, 2011-06-09T08:57:41Z, 1}}, {CategoriumContainer: categorium={2011-06-09T13:50:29Z, servizi pubblici, 2011-06-09T13:50:29Z, 2}}, {CategoriumContainer: categorium={2011-06-09T13:50:37Z, illuminazione, 2011-06-09T13:50:37Z, 3}}, {CategoriumContainer: categorium={2011-06-09T13:50:46Z, inquinamento, 2011-06-09T13:50:46Z, 4}}, {CategoriumContainer: categorium={2011-06-09T13:50:54Z, vandalismo, 2011-06-09T13:50:54Z, 5}}, {CategoriumContainer: categorium={2011-06-09T13:51:00Z, abbandono, 2011-06-09T13:51:00Z, 6}}, {CategoriumContainer: categorium={2011-06-15T08:33:17Z, altro, 2011-06-15T08:33:17Z, 8}}]

String[] c1Array = new String[results.length];
for (int i = 0; i < results.length; i++)
{
c1Array[i] = results[i].categorium.c1;
}
System.out.println(Arrays.toString(c1Array));
// output: [rete stradale, servizi pubblici, illuminazione, inquinamento, vandalismo, abbandono, altro]

return c1Array;
}
}

Answer to original version of question:

That's a terrible error message from Gson for the situation. I suggest logging an issue with them.

As posted in the current version of the question, the problem is you're trying to deserialize a JSON object as an array. Easy solutions to this problem are to either change the JSON into an array, or deserialize it as an object.

Here's an example that changes the JSON to have an array, and changes other things into what I guess you're trying to achieve.

import java.util.Arrays;

import com.google.gson.Gson;

public class Foo
{
public static void main(String[] args) throws Exception
{
new getElements().getEl();
}
}

class Thing
{
Categoria[] categorium;

@Override
public String toString()
{
return Arrays.toString(categorium);
}
}

class Categoria
{
public String created_at;
public String c1;
public String updated_at;
public int id;

public Categoria()
{
this.created_at = "";
this.c1 = "";
this.updated_at = "";
this.id = 0;
}

@Override
public String toString()
{
return String.format("{%s, %s, %s, %s}", created_at, c1, updated_at, id);
}
}

class getElements
{
String[] getEl() throws Exception
{
String stringa = "{\"categorium\":[{\"created_at\":\"2011-06-09T08:57:41Z\",\"c1\":\"rete stradale\",\"updated_at\":\"2011-06-09T08:57:41Z\",\"id\":1},{\"created_at\":\"2011-07-12T08:57:41Z\",\"c1\":\"asdf fdsa\",\"updated_at\":\"2011-07-12T08:57:41Z\",\"id\":2}]}";

Gson json = new Gson();
Thing thing = json.fromJson(stringa, Thing.class);
System.out.println(thing);
// output:
// [{2011-06-09T08:57:41Z, rete stradale, 2011-06-09T08:57:41Z, 1}, {2011-07-12T08:57:41Z, asdf fdsa, 2011-07-12T08:57:41Z, 2}]

Categoria[] cArray = thing.categorium;

String[] c1Array = new String[cArray.length];
for (int i = 0; i < cArray.length; i++)
{
c1Array[i] = cArray[i].c1;
}
System.out.println(Arrays.toString(c1Array));
// output: [rete stradale, asdf fdsa]

return c1Array;
}
}

java.lang.RuntimeException: Unable to invoke no-args constructor for class DBExecuter.Queryjson$valIOConfigclass

Mark your inner classes (valIOConfigclass and valCFGclass) as static

Gson Exception on deserialize (no-args constructor does not exist)

From Gson issue 255, The HTC Desire HD included an obsolete copy of Gson in its application classpath. That issue has instructions on using jarjar to repackage your version of Gson as to not conflict with the preinstalled version.

No args constructor for class does not exist', but it does

Gson cannot instantiate private nested classes. Make your Page class public:

public static class Page {...}


Related Topics



Leave a reply



Submit