Thursday, November 29, 2012

GSON Exclude / Skip class fields

I've been working on a project recently that uses GSON library to serialize POJO's  in JSON and store them in single database field. (We used this strategy for flexibility and ease of maintenance - no need for updating database schema every time model changes, but that's outside of this post topic). Since all objects where identified by their unique id property (integer or UUID), which was their primary key in RMDBS, there was no need to store this field in object's JSON representation. First idea that came is just to mark this field as transient

 public class Person {   
    ... field declarations ...  
    private transient int id;   
     ... getters / setters ..  
 }  

However, I had two problem's with this, one of pure technical nature, and one semantic

  • Keyword transient should be use to mark fields that are not supposed to persist. However, here's this is not the case, since id member IS stored in relational database.
  • This object are further exposed via SOAP service, thus id information would be lost when serializing object to XML
Digging further int GSON library, I've found that GsonBuilder has method setExclusionStrategies, which is pretty clear what id does, so when creating serializer we can specify exclusion strategy

  com.google.gson.Gson serializer = new com.google.gson.GsonBuilder().
     setExclusionStrategies(new com.google.gson.ExclusionStrategy() {  
       public boolean shouldSkipField(com.google.gson.FieldAttributes fieldAttributes) {  
         return "Person".equals((fieldAttributes.getDeclaredClass().getName())) && "id".equals(fieldAttributes.getName());  
       }  
       public boolean shouldSkipClass(Class<?> arg0) {  
         return false;  
       }  
     }).create();  


As you can see, all you have to do is implement com.google.gson.ExclusionStrategy interface. However, as mad as I am for generic and maintainable solutions, I did not like the fact this code is not extensible in easy and readable way, in term if there was a class User with property password I don't want to serialize, shouldSkipField method would look like:


  public boolean shouldSkipField(com.google.gson.FieldAttributes fieldAttributes) {  
         return "Person".equals((fieldAttributes.getDeclaredClass().getName())) && "id".equals(fieldAttributes.getName()) ||  
             "User".equals((fieldAttributes.getDeclaredClass().getName())) && "password".equals(fieldAttributes.getName());  
       }  

Quite ugly, right, specially, if there is more classes and fields to skip than two, we would get heavy-readable boolean expression. This can be improved, by simple externalizing 'configuration' outside of shouldSkipField and shouldSkipClass methods logic.  It's doable by simple storing this configuration as HashMap:

 package com.myapp.serialization  
   
 import java.util.Arrays;  
 import java.util.HashMap;  
 import java.util.Map.Entry;  
   
 import com.google.gson.ExclusionStrategy;  
 import com.google.gson.FieldAttributes;  
   
 public class JSONExclusionStrategy implements ExclusionStrategy{  
   
         private static HashMap<Class<?>,String[]> excludedFields;  
           
         public JSONExclusionStrategy(){  
             excludedFields = new HashMap<>();  
             //class maps to array of fields to skip in class  
             excludedFields.put(com.myapp.model.Person, new String[]{"id"});  
             excludedFields.put(com.myapp.model.User, new String[]{"password"});  
               
             //all arrays of fields are sorted lexically for faster lookup  
             for(Entry<Class<?>,String[]> entry : excludedFields.entrySet()){  
                 Arrays.sort(entry.getValue());  
             }  
         }  
           
   
         public boolean shouldSkipClass(Class<?> arg0) {  
             return false;  
         }  
   
         public boolean shouldSkipField(FieldAttributes fieldAttributes) {  
             if(excludedFields.containsKey(fieldAttributes.getDeclaredClass())){  
                 return Arrays.binarySearch(excludedFields.get(fieldAttributes.getDeclaredClass()),fieldAttributes.getName())>=0;   
             }  
             return false;  
         }  
 }  
   

 ...  
   com.google.gson.Gson serializer = new com.google.gson.GsonBuilder()  
     .setExclusionStrategies( new com.myapp.serialization.JSONExclusionStrategy()).create();  
 ..  


If further separation of configuration and code, we could wrap excluededFields dictionary into seprate class, and populate it from properties file or XML file. Another idea is to create annotation which would mark field as not serializable to JSON (and than read field's annotation in shouldSkipField method), though this requires code change. Hope anyone finds this post useful.

Tuesday, November 27, 2012

OOP Basics in Javascript

Though Javascript is quite old language (18 years exactly, in 2012), it can be used to write quite elegant and clean code in object-oriented manner.

Constructor

Object's constructor in Javascript is nothing more than simple function. There's no specially keyword for class declaration in Javascript, since Javascript is prototyped language, which means objects are created by cloning prototype object, rather than creating object out of the class definition, like, for an example in Java. 

JAVA

//class definition
class Time {
    int hours;
    int minutes;
    int seconds;
    // constructor
    public Time(int hours, int minutes, int seconds){
       this.hours = hours;
       this.minutes = minutes;
       this.seconds = seconds;
    }
}

Time t = new Time(21,29,00);

JAVASCRIPT
//constructor 
function Time(hh, mm, ss){
     var hours=hh,
         minutes = mm, 
         seconds = ss;
}

Fields (properties)

Due Javascript's dynamic nature, there is no need to declare fields on JS objects (though you can if you want default values). In terms of data structure you can think of JS objects as hashmap structure, with string as key type, similar to associative arrays in PHP:

 var obj = {}; // JSON representation of empty object
    obj.property = 'value';
    var key = 'property';   
    //Use variable to access object property in associative manner
    alert("Object's single property value is : " + obj[key]); 

 var obj = {}; // JSON representation of empty object
    obj.property = 'value';
    var key = 'property';   
    //Use variable to access object property in associative manner
    alert("Object's single property value is : " + obj[key]); 


Inheritance

As mentioned above, Javascript is prototyped language, so if we want to have inheritance behaviour, that would mean we want one prototype to inherit other prototype. When object is created, cloning is done by copying everything from object's prorotype property to cloned object:

      //parent 'class'
      var Dog = function(){
         
      }
     
      //we're creating method 'bark'
      Dog.prototype.bark = function(){
           alert('Woof, woof!')
      }

      function Husky(){
           //we're declaring a public method here by using this keyword
           this.getLifeExpactancy = function(){  
                  // wikipedia says 12 to 15, so I've took 12.5 as average
                return 13.5;
           }
      }
      
      var puppy1 = new Husky(); //we're cloning 'Husky' prototype
      alert('Puppy1 life expectancy: ' + puppy1.getLifeExpactancy());
      try {
          alert('Puppy1 barking');
          puppy1.bark();
       } catch (e) { 
           alert('This pup doesn\'t bark yet');
       }

       //Husky's prototype is a dog
       Husky.prototype = new Dog();

       //At this point we've changed Husky's prototype, 
      //but instantiated object's does not change
       if(typeof puppy1.bark == 'undefined'){
           alert('First puppy still doesn\'t bark')
       } else {
           throw 'Something is wrong here.' +
       'Already cloned objects from Husky prototype should not be changed';
       } 

       var puppy2 = new Husky();
       //Puppy2 should know how to bark
       alert('Puppy2 barking');
       puppy2.bark();
       
       var realHusky = new Husky();
       alert('Puppy3 is real husky, that knows how to bark');
       realHusky.bark();
       alert('And has life expectancy of ' + realHusky.getLifeExpactancy()
              + ' years');

       //if we want to inherit parent constructor also:
       Husky.prototype.constructor = Dog;
       try{  
          //Another way of instancing object - Object.Create
          //IMPORTANT!!! This is not compatible with all browsers (IE<9)
          var puppy3 = Object.create(Husky.prototype),
              puppy3lifeExpectancy = puppy3.getLifeExpactancy();
          alert('This should never get executed!');
       } catch(e){
          alert('By overriding Husky contructor' +
                ', we lost getLifeExpactancy method also');
       }




Public and private methods / fields

In Javascript there is no access modifiers like in languages like C# or JAVA, and there is no parallel to protected modifier in JAVA / C#. We achieve privacy of objects fields and functions by defining them in constructor. However, if we use keyword this, members will still be available outside of the object scope. More precisely, there's no such thing as 'object' scope in Javascript, there's only function-level scope. However, inside methods defined outside of constructor you can't access any of members defined inside constructor:

 var clazz = function() { 
        //declaring 'private' method inside of constructor
        var method = function() { 
            alert("Hello, world!!");
        }
    }

    clazz.prototype.methodWrapper = function() { 
          //this will always fail, since we are outside of clazz() scope
          method();
    }

    try{
        new clazz().methodWrapper();
    } catch(e) { 
         alert(e);
    } 
    
    var properClazz = function() { 
        var method = function(){
              alert("Hello, world!!");
        }

        // by using 'this' keyword we're making method
        // visible outside of constructor, in created 
        //  duplicates of properClazz prototype
        this.methodWrapper = function(){ 
             
             //at this point we are still in properClazz function scope, so 
             //we can access method variable, declared inside of this function
             method();
        }
    }
    //Greet the world
    new properClazz().methodWrapper();




Simulated namespacing

As JS projects tend to grow large these days, there is need for separating classes (prototypes) into different namespaces in order to avoid name collision. This can be emulated by making namespaces by simple JS objects. For an example, if we would like to have comparison of different implementations of same problem on one page (e.g. image compression), we would love our classes named same, so we would separate them into different ''namespaces''. See code below



       //creating 'namespaces' if does not exists. 
       var JPEG = JPEG  || {},
           JPEG2000 = JPEG2000 || {},
           JPEGLS = JPEGLS || {};

       JPEG.ImageEncoder = function() { 
                //   codec implementation
       }

       JPEG2000.ImageEncoder = function(){ 
              //    codec implementation
       }

       JPEGLS.ImageEncoder = function() { 
             //      codec implementation
       }

       var compare = function() { 
            var candidates = [ new JPEG.ImageEncoder(), 
                               new JPEG2000.ImageEncoder(),
                               new JPEGLS.ImageEncoder() ];
            for(var x in candidates){
               // measure performance for candidates[x]
            }

       }