NullDefense | Gson

Removes invalid objects during Gson parsing which are marked as required, yet null/empty.

Build Status Apache License v2.0 Latest Version

Code Quality

Codecov Codacy Grade Codebeat CodeFactor Codeclimate Maintainability Codeclimate Coverage


Installation

In build.gradle add the following dependencies

dependencies {
    compile 'com.venomvendor:gson-nulldefense:<latest.version>'
}

Usage Guide

Annotation

Marking required fields

Registering Adapter

TypeAdapterFactory nullDefenceAdapter = new NullDefenseTypeAdapterFactory(Mandatory.class);

Gson gson = new GsonBuilder()
        // Add null defense Adapter
        .registerTypeAdapterFactory(nullDefenceAdapter)
        // More options
        .enableComplexMapKeySerialization()
        .setPrettyPrinting()
        .setLenient()
        .serializeNulls()
        .create();

To Retain Empty Collection

TypeAdapterFactory typeAdapter = new NullDefenseTypeAdapterFactory(Mandatory.class)
         // To retain empty collection
         .retainEmptyCollection();

To Remove Empty Collection

TypeAdapterFactory typeAdapter = new NullDefenseTypeAdapterFactory(Mandatory.class)
         // To remove empty collection, this is default
         .removeEmptyCollection();

Using with Retrofit⬈

TypeAdapterFactory nullDefenceAdapter = new NullDefenseTypeAdapterFactory(Mandatory.class);

Gson gson = new GsonBuilder()
        // Add null defense Adapter
        .registerTypeAdapterFactory(nullDefenceAdapter)
        // More options
        . . .
        .create();

Retrofit retrofit = new Retrofit.Builder()
     // Pass custom gson
     .addConverterFactory(GsonConverterFactory.create(gson))
     // More options
        . . .
     .build();

Tests

POJO

public class Parent {

    @Mandatory
    private String name;

    @Mandatory
    private CustomList<Child> children;

    // Setter/Getter
}

public class Child {

    @Mandatory
    private String name;
    // I am optional
    private Boolean isMale;

    // Has no effect on primitive
    @Mandatory
    private int age;

    @Mandatory
    private Language language;

    // Setter/Getter
}

public class Language {

    @Mandatory
    private List<String> knownLanguages;

    // I am optional
    private List<String> learning;

    // Setter/Getter
}

parent-valid.json

{
  "name": "VenomVendor",
  "children": [
    {
      "name": "Queen",
      "isMale": false,
      "age": 26,
      "language": {
        "knownLanguages": [
          "Telugu",
          "Tamil"
        ],
        "learning": [
          "French"
        ]
      }
    },
    {
      "name": "Prince",
      "isMale": true,
      "age": 5,
      "language": {
        "knownLanguages": [
          "English",
          "Sanskrit"
        ],
        "learning": []
      }
    },
    {
      "name": "Princess",
      "isMale": false,
      "age": 3,
      "language": {
        "knownLanguages": [
          "Kannada"
        ],
        "learning": null
      }
    }
  ]
}
Result
assertEquals(3, parent.getChildren().size());

valid-missing-primitive.json

Annotation has no effect on primitive fields

{
  "name": "VenomVendor",
  "children": [
    {
      "name": "Queen",
      "isMale": false,
      "age": 26,
      "language": {
        "knownLanguages": [
          "Telugu",
          "Tamil"
        ],
        "learning": [
          "French"
        ]
      }
    },
    {
      "name": "Prince",
      "isMale": true,
      "age": null,
      "language": {
        "knownLanguages": [
          "English",
          "Sanskrit"
        ],
        "learning": []
      }
    },
    {
      "name": "Princess",
      "isMale": false,
      "language": {
        "knownLanguages": [
          "Kannada"
        ],
        "learning": null
      }
    }
  ]
}
Result
assertEquals(3, parent.getChildren().size());

missing-name-in-child.json

Should generate one child, as rest doesn’t have mandatory name

{
  "name": "VenomVendor",
  "children": [
    {
      /* Missing Mandatory Field */
      "isMale": false,
      "age": 26,
      "language": {
        "knownLanguages": [
          "Telugu",
          "Tamil"
        ],
        "learning": [
          "French"
        ]
      }
    },
    {
      "name": null, // Null Mandatory Field
      "isMale": true,
      "age": 5,
      "language": {
        "knownLanguages": [
          "English",
          "Sanskrit"
        ],
        "learning": []
      }
    },
    {
      "name": "Princess",
      "isMale": false,
      "age": 3,
      "language": {
        "knownLanguages": [
          "Kannada"
        ],
        "learning": null
      }
    }
  ]
}
Result
assertEquals(1, parent.getChildren().size());

missing-known-language-no-child.json

Should not generate any children due to missing knownLanguages, hence parent is also null, as it doesn’t have mandatory children

{
  "name": "VenomVendor",
  "children": [
    {
      "name": "Queen",
      "isMale": false,
      "age": 26,
      "language": {
        "knownLanguages": null,
        "learning": [
          "French"
        ]
      }
    },
    {
      "name": "Prince",
      "isMale": true,
      "age": 5,
      "language": {
        "knownLanguages": [],
        "learning": []
      }
    },
    {
      "name": "Princess",
      "isMale": false,
      "age": 3,
      "language": {
        "learning": null
      }
    }
  ]
}
Result
assertNull(parent);


More Tests⬈

Java Docs⬈

Code Coverage Codecov