Gson and Moshi differ in their deserialization of null to primitive types:
null for a primitive type, like int. It will result in 0.While I understand that the model should be Integer in cases where null is expected/allowed, this difference in both libraries makes the migration difficult.
Do you plan to allow null for primitive types? Maybe not by default but as an option on Moshi.Builder? If not this difference should at least be mentioned in the README.md.
This behavior can be done explicitly with an annotation like @DefaultInt(0) on the field and writing a @FromJson or JsonAdapter which handled this.
I kind of mimic the Gson behavior by using the following custom FromJson method:
@FromJson
public int intFromJson(@Nullable Integer value) {
if (value == null) {
// TODO: Log some kind of message to fix the POJO
return 0;
}
return value;
}
While I definitely want to get rid of this, this helps me to overcome any edge cases in my POJOs.
FYI: I had a hard time figuring out that a custom Nullable annotation is actually necessary. The one from the Support-Annotations has RetentionPolicy.CLASS, so Moshi can't see it at runtime and makes the adapter not-nullable. This isn't included in the docs, so maybe this would be worth noticing.
Thank you anyway for this great library!
@ChristianBecker thanks, this is very helpful.
@ChristianBecker thanks for the tip! I had to account for boolean values (and possibly other primitives as well) coming back as 'null'
So my adapter looks like this
class NullPrimitiveAdapter {
@FromJson
public int intFromJson(@Nullable Integer value) {
if (value == null) {
return 0;
}
return value;
}
@FromJson
public boolean booleanFromJson(@Nullable Boolean value) {
if (value == null) {
return false;
}
return value;
}
@FromJson
public double doubleFromJson(@Nullable Double value) {
if (value == null) {
return 0;
}
return value;
}
}
I also had to add a new Nullable annotation as @ChristianBecker suggested
@Retention(RetentionPolicy.RUNTIME)
@interface Nullable {
}
Works great @aneemtalukder and @osrl ! Since I am using proguard I also had to make sure the custom nullable annotation is not stripped / obfuscated.
I am keeping the interface as a private inner class so for me its (where OuterClass is my moshi provider class with the annotation as inner class / annotation:
-keep class com.packagename.OuterClass$Nullable { *; }
If you're using the annotation as a standalone class it should be something like:
-keep class com.packagename.Nullable** { *; }
Most helpful comment
@ChristianBecker thanks for the tip! I had to account for boolean values (and possibly other primitives as well) coming back as 'null'
So my adapter looks like this