Comments (12)
Extra info on the deserializing:
json = {"id":123,"thing":"AZ"}
Map<String, Object> decoded = gson.fromJson(data, new TypeToken<Map<String,
Object>>() {}.getType());
produces a map with: {id=java.lang.Object@e6612c, thing=java.lang.Object@d704f0}
(seems to be instances of Object with no data)
Original comment by azeckoski
on 15 Sep 2008 at 1:29
from google-gson.
First off, I'd like to start with some background information. When you are
defining
types (or local variables) that have type parameters, the JVM drops the actual
type
parameters and associates everything as "Object". This is known as "type
erasure".
In order for a Java Program to retrieve the actual type parameters at run-time,
you
need to leverage the TypeToken object (this methodology was established by
GUICE ---
see
http://google-guice.googlecode.com/svn/trunk/javadoc/com/google/inject/TypeLiter
al.html).
Originally, we implemented Gson so that it could "serialize" these kinds of
objects
without requiring the use of TypeToken; however, deserializing it back into the
real
object requires it since the JSON output has no type information in it. As
well,
with this approach, it meant you were serializing the "real" object which meant
that
some fields on the real object would be added to the JSON output. Therefore,
if you
had a List<A> and added both A and B objects (i.e. B extends A) some objects
would
expose extra fields in the output. We decided to take the more explicit route
and
force the client to provide us the type parameters of the top-level object that
is
being serialized.
The common use of a Map or List is that you populate the List with the same
object
types. Passing in Object means that you can add any instance of a class that
you
desire to the data structure. I know there are exceptions to this best
practice, but
we do not want to implement this corner case scenario. Instead, if you really
do
want to use a list of Objects, then do as the exception message says and write a
"custom" (de)serializer (you can bind it specifically to a Map<String, Object>
and
have the default Gson map serializer handle everything else).
As for a Map of Maps (i.e. Map<String, Map<String, Integer>>) this is already
supported and works well as long as you pass in the actual type object (i.e. new
TypeToken<Map<String, Map<String, Integer>>>() {}.getType())
Here's an example:
public static void main(String[] args) {
Type mapType = new TypeToken<Map<String, Map<String, Integer>>>() {}.getType();
Map<String, Map<String, Integer>> map = new HashMap<String, Map<String, Integer>>();
Map<String, Integer> value1 = new HashMap<String, Integer>();
value1.put("lalala", 78);
value1.put("haha", 9999);
map.put("id", value1);
Map<String, Integer> value2 = new HashMap<String, Integer>();
value2.put("nahhd", 121112);
value2.put("uuywss", 19987);
map.put("thing", value2);
Map<String, Integer> value3 = new HashMap<String, Integer>();
map.put("other", value3);
Gson gson = new Gson();
String json = gson.toJson(map, mapType);
System.out.println(json);
Map<String, Map<String, Integer>> deserializedMap = gson.fromJson(json, mapType);
System.out.println(deserializedMap);
}
=========== OUTPUT ===========
{"thing":456,"id":123}
{"other":{},"thing":{"nahhd":121112,"uuywss":19987},"id":{"lalala":78,"haha":999
9}}
{other={}, thing={nahhd=121112, uuywss=19987}, id={lalala=78, haha=9999}}
For now, I am closing this off as "Working as Designed". Maybe I am not
completely
following your issue and if that is the case, please start up a new discussion
in our
Gson discussion group.
Thanks,
Joel
Original comment by [email protected]
on 16 Sep 2008 at 8:57
- Changed state: Invalid
from google-gson.
We solved our problem by using a different library but I wanted to put a
comment here
anyway.
So what happens if I want to do this?
Map<String, Number>
or
Map<String, Serializable>
(it seems to fail)
It seems that this is designed to only work for the basic case where I have
really
simple and non-nested structures where all the beans are easily instantiable
and not
superclasses. It is a shame that this is considered working as designed.
Original comment by azeckoski
on 18 Sep 2008 at 9:01
from google-gson.
I am glad to hear that you found something that works for you, but it's too bad
you
are unable to use Gson. I'd still like to follow up on this issue because it is
user's like yourself that will help to advance this library.
First off, are you serializing and deserializing an object of type Map<String,
Number>? If it is serialization only, than that is a much "easier" problem to
solve
because we have the runtime types. As for "deserializing" this kind of object,
we
have provided our clients with the concept of a custom "Type Adapter". You
should be
able to write a type as follows to get it to work with "Number":
public static class NumberTypeAdapter
implements JsonSerializer<Number>, JsonDeserializer<Number>,
InstanceCreator<Number> {
public JsonElement serialize(Number src, Type typeOfSrc, JsonSerializationContext
context) {
return new JsonPrimitive(src);
}
public Number deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context)
throws JsonParseException {
JsonPrimitive jsonPrimitive = json.getAsJsonPrimitive();
if (jsonPrimitive.isNumber()) {
return jsonPrimitive.getAsNumber();
} else {
throw new IllegalStateException("Expected a number field, but was " + json);
}
}
public Number createInstance(Type type) {
return 1L;
}
}
public static void main(String[] args) {
Map<String, Number> map = new HashMap<String, Number>();
map.put("int", 123);
map.put("long", 1234567890123456789L);
map.put("double", 1234.5678D);
map.put("float", 1.2345F);
Type mapType = new TypeToken<Map<String, Number>>() {}.getType();
Gson gson = new GsonBuilder().registerTypeAdapter(Number.class, new
NumberTypeAdapter()).create();
String json = gson.toJson(map, mapType);
System.out.println(json);
Map<String, Number> deserializedMap = gson.fromJson(json, mapType);
System.out.println(deserializedMap);
}
========== OUTPUT ==========
{"double":1234.5678,"float":1.2345,"int":123,"long":1234567890123456789}
{double=1234.5678, float=1.2345, int=123, long=1234567890123456789}
We should probably just include the above type adapter as a default in Gson and
I
will discuss this with Inderjeet. There is a bug, however, since you actually
have
to specify a "instance creator" for this type of object (i.e. primitive), but I
will
have that fixed by the next release. You should be able to write something
similar
as above for "Serializable".
I hope this information is helpful and thanks for the all the feedback on this
library.
Original comment by [email protected]
on 27 Sep 2008 at 8:32
from google-gson.
I modify the MapTypeAdapter to match the jdk14's Map
======================================================
public JsonElement serialize(Map src, Type typeOfSrc, JsonSerializationContext
context) {
JsonObject map = new JsonObject();
//Type childType = new TypeInfoMap(typeOfSrc).getValueType();
for (Iterator iterator = src.entrySet().iterator(); iterator.hasNext(); ) {
Map.Entry entry = (Map.Entry) iterator.next();
Object obj = entry.getValue();
JsonElement valueElement = context.serialize(obj, obj.getClass());
---------------------------------------------------------------------modified
map.add(entry.getKey().toString(), valueElement);
}
return map;
}
--------------------------------------------------------------------------------
and then the map class can be used like this:
HashMap aaaa = new HashMap();
aaaa.put("aa", 1212);
aaaa.put("bb", "fasdfa");
System.out.println(gson.toJson(aaaa));
==========output=================
{"bb":"fasdfa","aa":1212}
=================================
It can run, good or bad? because there are lot's of jdk14's source code in many
project's.
Original comment by [email protected]
on 21 Oct 2008 at 9:53
from google-gson.
Thanks for providing the code snippet. This will not work properly in case of
genericized maps since in those cases it is important to use the type specified
in
the field declaration instead of the actual type. I have made similar fixes for
Issue
54 and 58 that I will apply in this case as well.
Original comment by inder123
on 21 Oct 2008 at 3:32
from google-gson.
I have fixed this issue in r277
Now, you should be able to serialize raw maps. The deserialization continues to
require parameterized type.
Original comment by inder123
on 21 Oct 2008 at 10:41
- Changed state: Fixed
from google-gson.
Thank you for fixing this issue:
In java land, you really shouldn't be instantiating Map<String, Object> but
since
we're dealing with JSON world, it actually makes a lot of sense.
Consider Map<String, Object> map;
map.put("field1", 123);
map.put("field2", "myfield2");
What is gson.toJson(map)???
It's a javascript object o where o.field1 is the number 123 and o.field2 is the
string myfield2!
Original comment by [email protected]
on 22 Jan 2010 at 9:43
from google-gson.
json convert to map<Integer,MyClass> it have problem !
how to do ?
Original comment by [email protected]
on 6 Mar 2010 at 6:43
from google-gson.
If you do json eval() in javascript or python, you get a dictionary. Inside the
dictionary, it has String/Number or nested dictionaries. eval doesnt expect
these type declarations.
I would expect the same on static language as well - Maps with default Number
(lossless datatype like Double) datatype for deserialization.
Original comment by [email protected]
on 25 Jun 2010 at 6:12
from google-gson.
Hi demograp,
Did you forget to implement a default constructor for MyClass ?
It was my case, and I solved it doing this.
Hope it helps.
Original comment by [email protected]
on 6 Aug 2010 at 2:45
from google-gson.
I faced similar problems. Easiest solution for me was wrapping the desired map
in a wrapper object and passing that to gson. I guess in the end that just
boils down to be the same as providing the TypeToken, but it is a much more
straightforward solution for those who want a quick fix.
Original comment by [email protected]
on 1 Sep 2011 at 12:23
from google-gson.
Related Issues (20)
- Should support custom serializers for map keys HOT 4
- please add support for getter method HOT 1
- Permit type data in the serialized JSON HOT 7
- Unbearable when toJson a long string(1M) HOT 2
- Gson should provide a way to configure order for field navigation HOT 5
- Not able to deserialize. HOT 2
- Not able to deserialize. HOT 3
- support java.sql.Date and Timestamp types HOT 6
- Having an inner class gives this error - No-args constructor for B does not exist. HOT 1
- Extend Expose annotation to support classes HOT 3
- Support circular references HOT 18
- Gson should have a way to provide custom exclusion strategies HOT 2
- all should be strings HOT 2
- Error Deserializing objects using fromJson(string, type) HOT 4
- com.google.gson.Gson should be able to toJson JsonElements/JsonObjects HOT 3
- Deserialization/Serialization issue when json is injected via spring annotations HOT 5
- Set formatting style in pretty printing HOT 1
- suggestion: Add @Verification annotation for easy verification of POJO validity HOT 6
- compilation via maven fails due to generics bug in javac HOT 1
- Gson needs a more obust inclusion and exclusion mechanism HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from google-gson.