Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

User guide is wrong: Inner classes can now be serialized/deserialized? #534

Open
GoogleCodeExporter opened this issue Mar 19, 2015 · 5 comments

Comments

@GoogleCodeExporter
Copy link

commented Mar 19, 2015

The user guide states:

https://sites.google.com/site/gson/gson-user-guide#TOC-Nested-Classes-including-
Inner-Classes-

"Gson can not automatically deserialize the pure inner classes since their 
no-args constructor also need a reference to the containing Object which is not 
available at the time of deserialization."

This is no longer true (I think because of UnsafeAllocator?), and should be 
documented. The example, which previously didn't work, now does. See the 
following:


public class A {
  public String a; 

  public class B {
    public String b; 

    public B() {
    }
  }

  public static void main(String[] arguments) {
    Gson gson = new Gson();
    B b = new A().new B();

    String json = gson.toJson(b);
    System.out.println("gson.toJson(" + b + ") = " + json);
    B b2 = gson.fromJson(json, B.class);
    System.out.println("gson.fromJson(..., B.class) = " + b2);
  }
}

The output of this is:

gson.toJson(co.mitro.core.server.data.A$B@7c97cb70) = {}
gson.fromJson(..., B.class) = co.mitro.core.server.data.A$B@b45ad3d

HOWEVER: If you try to reference the parent class from b2, you get a 
NullPointerException, which is fairly surprising and "dangerous." This needs to 
at least be documented! The debate about if this is the right default is a 
different discussion (I know that GsonBuilder.disableInnerClassSerialization() 
can turn this off)


Original issue reported on code.google.com by e...@evanjones.ca on 26 Sep 2013 at 2:27

@khashish

This comment has been minimized.

Copy link

commented Jun 27, 2016

Any updates on this issue?

@remyvrs

This comment has been minimized.

Copy link

commented Feb 26, 2018

my hack was this :

GsonBuilder gsonBuilder = new GsonBuilder();
final A a = new A();
gsonBuilder.registerTypeAdapter(A.class, (InstanceCreator) type -> a);
gsonBuilder.registerTypeAdapter(A.B.class, (InstanceCreator<A.B>) type -> a.new B());
gson = gsonBuilder.create();

clearly it works only when having in mind only one A instance ...

@remyvrs

This comment has been minimized.

Copy link

commented Feb 27, 2018

My previous hack does not work for a tree where more than one instance of A is created. In case anyone needs it the solution applied by is :
instead of
gsonBuilder.registerTypeAdapter(A.class, (InstanceCreator) type -> a);
gsonBuilder.registerTypeAdapter(A.B.class, (InstanceCreator<A.B>) type -> a.new B());

I used :

	InnerClassInstanceCreator innerClassInstanceCreator = new InnerClassInstanceCreator();
	gsonBuilder.registerTypeAdapter(A.class, innerClassInstanceCreator);
	gsonBuilder.registerTypeAdapter(A.B.class, innerClassInstanceCreator);


private static class InnerClassInstanceCreator implements InstanceCreator<Object> {

	private A a;

	@Override
	public Object createInstance(Type type) {
		if (type.equals(A.class))
			return a = new A();
		else if (type.equals(A.B.class))
			return a.new B();
		else
			return null;
	}
}
@Avacadros

This comment has been minimized.

Copy link

commented Mar 21, 2018

GsonBuilder gsonBuilder = new GsonBuilder(); final A a = new A(); gsonBuilder.registerTypeAdapter(A.class, (InstanceCreator) type -> a); gsonBuilder.registerTypeAdapter(A.B.class, (InstanceCreator<A.B>) type -> a.new B()); Gson gson = gsonBuilder.create();

The above code from @remyvrs was super helpful to me. Consider PrettyPrint if you're using this to debug, as it's almost no extra work and is quite helpful:

Gson gson = new GsonBuilder().setPrettyPrinting().create();

@Rutishauser

This comment has been minimized.

Copy link

commented Sep 6, 2019

OK. There is some issue of deserializing an inner class alone. But there should be no problems with deserializing the inner class together with the outer class. Why isn't this implemented?
public class Outer { Inner x; public class Inner {...} }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.