gson: Deserialization with Gson.fromJson() should *ignore* missing fields
What steps will reproduce the problem?
1. Create a simple *non-static* class which initializes default values for some
fields:
public class Test {
int x = -1;
String s = "Hello";
}
2. Create new Gson and call `fromJson()` with missing fields:
Test t = new Gson().fromJson("{}", Test.class);
System.out.println(String.format("x=[%s] s=[%s]", t.x, t.s));
>> Results: x=[0] s=[null]
Test t = new Gson().fromJson("{\"x\": 1}", Test.class);
System.out.println(String.format("x=[%s] s=[%s]", t.x, t.s));
>> Results: x=[1] s=[null]
What is the expected output? What do you see instead?
As the test cases, I would like to expect default value for each field to be
the one that the class initializes. For instance with the first test case, `x`
should be `-1` and `s` should be "Hello".
What version of the product are you using? On what operating system?
- Gson 2.2.3
- OSes:
+ Fedora 18, 64 bit with OpenJDK 1.7.0_19;
+ Android API 4 and API 17;
Thanks,
Hai
Original issue reported on code.google.com by haibison...@gmail.com
on 5 May 2013 at 8:23
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Reactions: 37
- Comments: 33 (1 by maintainers)
Commits related to this issue
- Integrate quantity selector into ViewModel and store quantities to pay Make separate BillItem and orderItem to avoid having to assign default values to everything (https://github.com/google/gson/issue... — committed to rntrtul/QuickBill by rntrtul 2 years ago
- Check if releasesList is empty (#2183) When deserializing with Gson, non-existent blocks are assigned to null https://github.com/google/gson/issues/513 — committed to LSPosed/LSPosed by Howard20181 2 years ago
Still a problem.
Any update on this?
This is still a problem. I’m going to have to use a different library because of this. Very disappointing…
For me it works with 2.8.5 only if all fields have defaults
but when one has no default
Works in 2.8.2. Declare the User class static or define it outside of another class. Update: actually, it works in 2.2.4 too.
Original comment by
krt...@gmail.com
on 22 Nov 2013 at 1:12This is still a problem, is anyone looking into this? How do we prevent null fields from being deserialized?
The 2020 comment from @Marcono1234 remains correct. If you are seeing this problem for a class that is not an inner class (it’s a top-level class, or it’s
static
) and that has a no-arg constructor, then please open a separate bug with a minimal test case that reproduces the problem. Otherwise, the solution is probably to register aTypeAdapter
for your class.Concerning Kotlin, it doesn’t work if some but not all fields in a
data class
have default values. If all fields do have default values then the Kotlin compiler generates a no-arg constructor:This part of the reproduction steps hints where the issue is. Since the class is an non-static (i.e. inner) nested class the compiler adds a synthetic constructor parameter for passing the enclosing instance. Therefore Gson is not able to find a no-parameter constructor and falls back to using the JDK internal method
sun.misc.Unsafe.allocateInstance
whose documentation says:(which apparently includes the initializers assigning the field values as well)
There are at least two solutions for this:
static
; often this is possible without any additional code changes and likely will also improve the performance of your codeInstanceCreator
; this can be more tricky since you somehow have to access an instance of the enclosing class to create an instance of the inner class. Implementing this correctly and in a sane way depends on your use case.The Kotlin case described in https://github.com/google/gson/issues/513#issuecomment-447299253 seems to be similar. It appears when all fields have a default value the Kotlin compiler creates a no-parameter constructor. However, as soon as one field has no default value there won’t be a no-parameter constructor so Gson falls back to using Unsafe as described above. The solution here could be to add a default value for all fields (even if you expect some of them to always be overwritten) or to write a custom
TypeAdapter
.modify ReflectiveTypeAdapterFactory
add deserializeNulls to GsonBuilder and Gson
Thank you. I didn’t describe clearly. I debug the Gson source code.And I found why my result is username not null. You can follow the call chain,you will found the method in Gson.java
and the typeAdapter is instanceof Adapter in ReflectiveTypeAdapterFactory. and the method read() is
‘T instance = constructor.construct();’ After this,instance is initialize its parameter. In my code, the parameter ‘name’ is initialize to ‘username’. And in.hasNext()==false, so the method just return instance. For more detail, the code ’ constructor.construct()’ user the java reflect
although ‘args ==null’ ,the instance initialize its parameter with default value. I did in jdk1.7 and jdk1.8 . Did I describe clearly ? I tried my best. Sorry , I will improve my English.
I’m having the same problem right now. That link does not help, it’s about something else @VyshnavKR
@stayclean I don’t remember the solution but I have done it all well. Will this help? stackoverflow.com/questions/33435683/deserialize-with-gson-and-null-values