Moshi: Allow null-values for primitive types

Created on 21 Dec 2015  路  6Comments  路  Source: square/moshi

Gson and Moshi differ in their deserialization of null to primitive types:

  • Gson allows null for a primitive type, like int. It will result in 0.
  • Moshi is strict in this way and will throw an exception.

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.

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

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;
    }
}

All 6 comments

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** { *; }

Was this page helpful?
0 / 5 - 0 ratings