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
Sort Arrays of Primitive Types in Descending Order
Jpanel & Components Change Position Automatically
Differencebetween ? and Object in Java Generics
Exposed Beyond App Through Clipdata.Item.Geturi
Android - Preventing Webview Reload on Rotate
How to Change Text of a Textview in Navigation Drawer Header
Deprecated Managedquery() Issue
Jcenter Deprecation; Impact on Gradle and Android
Disable Ssl Certificate Check in Retrofit Library
When Is Onattach Called During the Fragment Lifecycle
Is Default No-Args Constructor Mandatory for Gson
Mapstruct and Lombok Not Working Together
Getextractedtext on Inactive Inputconnection Warning on Android
Elegant Way to Read File into Byte[] Array in Java
How to Properly Implement Parcelable with an Arraylist<Parcelable>