discomarathon / google-gson

Automatically exported from code.google.com/p/google-gson
0 stars 0 forks source link

unable to serialize an object with list of other objects #170

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
interface IPerson {
  String getName();
}

public class Person implements IPerson {
  private String name;
  public Person() { 
  } 
  public Person(String name) {
    this.name = name;
  }
  @Override
  public String getName() {
    return name;
  }
}

public class People {
  private List<IPerson> people = new LinkedList<IPerson>();
  public People() {
  }
  public People(List<IPerson> people) {
    this.people = people;
  }
  public List<IPerson> getPeople() {
    return people;
  }
}

@Test
public void testGsonProjects() {
  People people = new People(asList((IPerson) new Person("Obama")));
  String json = new Gson().toJson(people);  
  System.out.println(json);
}

expected: {people:[{name:"Obama"}]}
actual  : {people:[{}]}

affected version: 1.3, 1.4

Original issue reported on code.google.com by luca.marrocco on 30 Oct 2009 at 11:33

GoogleCodeExporter commented 9 years ago
I have not used asList() before, but I understand that that is to get a List 
backed
up by an Array. (It is a static method of an Array).

I can't see that the Person class is an Array. Doesn't the compiler report an 
error
on this code?

Also, isn't the syntax to be Array.asList<IPerson>(yourArray)?

Array<IPerson> peopleArray = new ArrayList<IPerson>(); // e.g.
peopleArray.add(new Person("Obama"));
peopleList = Array.asList(peopleArray); // I have no idea how to get the list 
as a
LinkedList
People people = new People(peopleList);

Also, I think that you should move the "private List<IPerson> people = new
ListnkedList<IPerson>();" to inside "public People()". Because this new 
instance of
the List is not needed for the next constructor, i.e. public People(List...);

Probably you should just declare the member as "private List<IPerson> people;"

Original comment by takayama...@gmail.com on 15 Feb 2010 at 11:28

GoogleCodeExporter commented 9 years ago
Hello, thank you for your reply.

asList works (almost) if you do an static import of java.util.Arrays.*;
But anyway that is not the point. 

Here is new test without the "asList" and GSON is not producing the expected 
result.

public void testGsonProjects() {
  List<IPerson> personList = new LinkedList<IPerson>();
  personList.add(new Person("Obama"));
  personList.add(new Person("Clinton"));

  People people = new People(personList);
  String json = new Gson().toJson(people);
  System.out.println(json);
}

Expected:
{"people":[{"name":"Obama"},{"name":"Clinton"}]}

Actual:
{"people":[{},{}]}

However, toJson(personList) produces:
[{"name":"Obama"},{"name":"Clinton"}]

This is very weird.

Original comment by jevgenij...@gmail.com on 16 Feb 2010 at 3:57

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
i have the following code using json-lib

String response = put(command.toString());
JsonConfig jsonConfig = new JsonConfig();
jsonConfig.setExcludes(new String[]{"cookie", "length"});
final JSONArray jsonResponse = (JSONArray) 
JSONSerializer.toJSON(response,jsonConfig);

I have to rewrite this code on Android using gson.. I could not find a 
configurable
Json de-serialzer where i can write excludes as above. Does any one have any 
idea how
i can do so.

Original comment by daljeet....@gmail.com on 16 Feb 2010 at 7:16

GoogleCodeExporter commented 9 years ago
To: jevgenij.tsoi

Now your code has less error. To use a List in Gson, you have to declare the 
type of
the list to Gson. You either register it with Gson or give it as an argument to 
toJson().

It is documented here:

http://sites.google.com/site/gson/gson-user-guide#TOC-Collections-Examples

Original comment by takayama...@gmail.com on 16 Feb 2010 at 11:20

GoogleCodeExporter commented 9 years ago
I am sorry, but that seems a bit strange.

Are you saying GSON cannot serialize Lists unless it know what type they are?
In that case (new Gson()).toJson(personList); should NOT produce a valid result.
but it does.

Let me sum it up:
Typed list as a member in an object -> the object is serialized but all the list
elements are empty "{}"

Untyped list as a member in an object -> works fine.

Typed list directly, without type info to Gson -> works fine.

How come the Untyped case works but the typed case does not?
It should default to the untyped case. Do you not agree?

Original comment by jevgenij...@gmail.com on 17 Feb 2010 at 8:48

GoogleCodeExporter commented 9 years ago
I am sorry, but that seems a bit strange.

Are you saying GSON cannot serialize Lists unless it know what type they are?
In that case (new Gson()).toJson(personList); should NOT produce a valid result.
but it does.

Let me sum it up:
Typed list as a member in an object -> the object is serialized but all the list
elements are empty "{}"

Untyped list as a member in an object -> works fine.

Typed list directly, without type info to Gson -> works fine.

How come the Untyped case works but the typed case does not?
It should default to the untyped case. Do you not agree?

Original comment by jevgenij...@gmail.com on 17 Feb 2010 at 8:49

GoogleCodeExporter commented 9 years ago
Gson can serialize it fine but will not be able to deserialize an untyped 
collection.

The Typed list in the code sample is declared as List<IPerson>. However, 
IPerson has 
no fields (since it is an interface). Hence Gson serializes it as an empty 
object. In 
the case of Untyped collection, Gson uses the actual class of the objects in 
the 
collection, and is able to serialize them since it sees their fields.

Original comment by inder123 on 17 Feb 2010 at 9:48

GoogleCodeExporter commented 9 years ago
Oh, I did not realise that. Obviously I have not used it in the similar way 
before.

So, the solution is to declare the type of the list with a concrete class which 
has
implemented the interface?

Original comment by takayama...@gmail.com on 17 Feb 2010 at 11:04

GoogleCodeExporter commented 9 years ago
Sorry but I think the OP has a point that has still not been addressed.  

Forgetting about de-serialization entirely for the time being, why does GSON 
correctly serialize a typed collection when passed directly the the toJson() 
method, 
but not when it is a member variable of a parent class?

If I have a List<Shape> that contains Circle objects, and serialize the list 
(using 
GSON v1.4) the resulting JSON correctly includes the fields from the Shape 
(position) 
and Circle (radius). However, if I add my List<Shape> as a member variable 
'shapes' 
of a Canvas object and serialise that, all I get is the positions and none of 
the 
subclass fields.

If I need my list to contain Circles and Squares, I can't simple promote the 
list to 
the correct concrete type as suggested here. 

Original comment by charles%...@gtempaccount.com on 3 Jun 2010 at 6:16

GoogleCodeExporter commented 9 years ago
I've opened issue 231 to track the polymorphism issue.

In the interim, you'll have to work around this with a custom JsonSerializer.

Original comment by limpbizkit on 28 Aug 2010 at 6:03

GoogleCodeExporter commented 9 years ago
I had the same problem.

I had to patch the CollectionTypeAdapter because I couldn't register my own 
Adaptater on java.util.Collection.

Original comment by jprudent@gmail.com on 22 Oct 2010 at 9:38