title: How to ignore null fields in ExtJS data models?
body: <p>My question is very long... So, be patient :)</p>
  
  <p>I'm working with models in ExtJS 4, but I'm having some problems with the associations, so I created a function to perform the automatic model creation for me. Lets suppose I need to parse the following JSON:</p>
  
  <pre><code>{ 
      "success": true, 
      "total": 28, 
      "itens": [{
          "id":1,
          "nome":"ACRE",
          "sigla":"AC",
          "pais":{
              "id":31,
              "nome":"BRASIL",
              "sigla":"BR"
          }
      },{
          "id":2,
          "nome":"ALAGOAS",
          "sigla":"AL",
          "pais":{
              "id":31,
              "nome":"BRASIL",
              "sigla":"BR"
          }
      }, ...]
  }
  </code></pre>
  
  <p>The itens represent Provinces (Estados in Brazilian portuguese) which have a Country (País in brazilian portuguese). I tried to use ExtJS associations, but I thought that it works like Java relationships and I was wrong. Well, for this JSON I have these Java classes and these Ext Models (the models are created using the function provided too).</p>
  
  <p><strong>Pais.java</strong></p>
  
  <pre><code>@Entity
  // named queries here...
  public class Pais implements Serializable {
  
      @Id
      @GeneratedValue
      private Long id;
  
      @NotNull
      @NotEmpty
      @Length( max = 100 )
      private String nome;
  
      @NotNull
      @NotEmpty
      @Column( unique = true )
      @Length( min = 2, max = 4 )
      private String sigla;
  
      // getters, setters, equals, hashCode and toString here
  
  }
  </code></pre>
  
  <p><strong>Estado.java</strong></p>
  
  <pre><code>@Entity
  // named queries here...
  public class Estado implements Serializable {
  
      @Id
      @GeneratedValue
      private Long id;
  
      @NotNull
      @NotEmpty
      @Length( max = 100 )
      private String nome;
  
      @NotNull
      @NotEmpty
      @Column( unique = true )
      @Length( min = 2, max = 4 )
      private String sigla;
  
      @NotNull
      @ManyToOne
      private Pais pais;
  
      // getters, setters, equals, hashCode and toString here
  
  }
  </code></pre>
  
  <p><strong>Function to create the models</strong></p>
  
  <pre><code>Ext.ns( "Uteis" );
  
  // other utility functions here...
  
  Uteis.createModel = function( modelData ) {
  
      var fields = modelData.fields;
      var processedFields = [];
      var normalFields = [];
      var relationFields = [];
  
      for ( var i in fields ) {
  
          if ( fields[i].type ) {
  
              switch ( fields[i].type ) {
  
                  case "auto":
                  case "string":
                  case "int":
                  case "float":
                  case "boolean":
                  case "date":
                      normalFields.push( fields[i] );
                      break;
  
                  default:
  
                      var relationField = fields[i];
  
                      var prefix = relationField.name + ".";
                      var modelInstance = Ext.create( relationField.type );
  
                      modelInstance.fields.each( function( item, index, length ) {
  
                          var newField = {};
  
                          // I used this sintax to make possible create only some fields
                          // if I need in the future.
                          newField["name"] = prefix + item.name;
                          newField["type"] = item.type.type;
  
                          newField["convert"] = item.convert;
                          newField["dateFormat"] = item.dateFormat;
                          newField["defaultValue"] = item.defaultValue;
                          newField["mapping"] = item.mapping;
                          newField["persist"] = item.persist;
                          newField["sortDir"] = item.sortDir;
                          newField["sortType"] = item.sortType;
                          newField["useNull"] = item.useNull;
  
                          relationFields.push( newField );
  
                      });
  
                      break;
  
              }
  
          } else {
              normalFields.push( fields[i] );
          }
  
      }
  
      processedFields = normalFields.concat( relationFields );
  
      // debugging code
      /*console.log( "*** " + modelData.name );
      for ( var i in processedFields ) {
          console.log( processedFields[i] );
      }*/
  
      Ext.define( modelData.name, {
          extend: "Ext.data.Model",
          fields: processedFields
      });
  
  };
  </code></pre>
  
  <p><strong>Using function to create the models</strong></p>
  
  <pre><code>Uteis.createModel({ 
      name: "Modelos.Pais",
      fields: [
          { name: "id",  type: "int" },
          { name: "nome",  type: "string" },
          { name: "sigla",  type: "string" }
      ]
  });
  
  Uteis.createModel({ 
      name: "Modelos.Estado",
      fields: [
          { name: "id",  type: "int" },
          { name: "nome",  type: "string" },
          { name: "sigla",  type: "string" },
          { name: "pais", type: "Modelos.Pais" } // &lt;= references the model created above
      ]
  });
  </code></pre>
  
  <p>The code above is correspondent to this. I created the function to automatize the creation of nested data fields (because the problem of the associations that I said).</p>
  
  <pre><code>Ext.define( "Modelos.Pais", {
      extend: "Ext.data.Model",
      fields: [
          { name: "id",  type: "int" },
          { name: "nome",  type: "string" },
          { name: "sigla",  type: "string" }
      ]
  });
  
  Ext.define( "Modelos.Estado", {
      extend: "Ext.data.Model",
      fields: [
          { name: "id",  type: "int" },
          { name: "nome",  type: "string" },
          { name: "sigla",  type: "string" },
          { name: "pais.id",  type: "int" },
          { name: "pais.nome",  type: "string" },
          { name: "pais.sigla",  type: "string" }
      ]
  });
  </code></pre>
  
  <p>Ok, these models (created using my createModel function) work very well with my JsonStores. Until now, all of the mapping associations in the Java side were not null, so, my stores always have nested data to process. Now, I have to process some entities that can have null associations and my problems began. The store that needs to deal with this scenario not works (an exception is being thrown in the store operation, saying that the fields are null). I'm using Gson to create JSON from my entities. Its default behaviour is to not serialize null fields, them they will be undefined in the client side, so I though that if I serialize the null fields (sending a null) would make Ext to realize the null field and not try to process it. To do this I used this code to create the Gson:</p>
  
  <pre><code>Gson gson = new GsonBuilder().serializeNulls().create();
  </code></pre>
  
  <p>Ok, now the JSON with null associations is being generated, but the Ext continues to complain. I tried to use the field mapping and defaultValue configs with no success. To make the things simpler, lets use the example of Estados and Países (Privinces and Countries) where Pais is not @NotNull anymore. The JSON with a null pais would be like:</p>
  
  <pre><code>{ 
      "success": true, 
      "total": 28, 
      "itens": [{
          "id":1,
          "nome":"ACRE",
          "sigla":"AC",
          "pais":null   // &lt;= here
      },{
          "id":2,
          "nome":"ALAGOAS",
          "sigla":"AL",
          "pais":{  // this is not null
              "id":31,
              "nome":"BRASIL",
              "sigla":"BR"
          }
      }, ...]
  }
  </code></pre>
  
  <p>With this code, the pais.id, pais.nome and pais.sigla fields would not be available, since the pais property is null. So, my question is: <strong>How to make the store ignore some fields when they are null or undefined?</strong> I already tried to search for a solution with no success... Thank you very much!</p>
  
  <p><strong>Edit</strong>: After thinking the entire night in some possible solutions at server side, I implement a solution in the last 15 minutes, but I definatelly don't like it... Its a reflective method to traverse each object "object tree" before using Gson to set default values to fields that are null. It is working, but the JSON is becoming unnecessarily too big. The traversal method:</p>
  
  <pre><code>/**
   * A method to traverse the object tree and set "default" values to null fields.
   * 
   * @param target The object to be inspected.
   */
  public static void traverseAndSetDefaultValue( Object target ) {
  
      try {
  
          for ( Field f : target.getClass().getDeclaredFields() ) {
  
              // ok to change...
              f.setAccessible( true );
  
              // is null? so create something
              if ( f.get( target ) == null ) {
  
                  // new instance of the current field
                  Object newInstance = null;
  
                  // it needs to traverse to the next level?
                  boolean okToTraverse = false;
  
                  switch ( f.getType().getSimpleName() ) {
  
                      case "Byte":
                      case "Short":
                      case "Integer":
                          newInstance = 0;
                          break;
  
                      case "Long":
                          newInstance = 0L;
                          break;
  
                      case "Float":
                          newInstance = 0F;
                          break;
  
                      case "Double":
                          newInstance = 0D;
                          break;
  
                      case "Character":
                          newInstance = '\0';
                          break;
  
                      case "Boolean":
                          newInstance = Boolean.FALSE;
                          break;
  
                      case "String":
                          newInstance = "";
                          break;
  
                      case "List":
                          newInstance = new ArrayList();
                          break;
  
                      case "Set":
                          newInstance = new HashSet();
                          break;
  
                      default:
                          // calling the default constructor for no 
                          // "default" types
                          newInstance = f.getType().newInstance();
                          okToTraverse = true;
                          break;
  
                  }
  
                  f.set( target, newInstance );
  
                  if ( okToTraverse ) {
                      traverseAndSetDefaultValue( newInstance );
                  }
  
              }
  
          }
  
      } catch ( IllegalAccessException | InstantiationException exc ) {
          exc.printStackTrace();
      }
  
  }
  </code></pre>
  
  <p>I would like what do you think about it... Thank you!</p>
  
  <p><strong>Edit 2</strong>: Hello again. I give up! :) I will use my solution that I posted above.I found <a href="http://www.sencha.com/forum/showthread.php?182147-Success!-Nested-data-in-Grids-Custom-setters-amp-getters-JsonPath-and-Relationships" rel="nofollow">some patches</a> to improve the relationship with models and grids. I tested they, but the problem with null fields continues (at least the error disapeared). Ok, now is time to continue the development. When the application is finished I will go back to this issue to try to improve my solution. Thank you!</p>