         }
     }
     
-    //display property name and value friendly
+    /// display property name and value friendly
     override open var description: String {
         let selfClass = type(of: self)
         var desc = "|\(selfClass)| "
         for info in selfClass.propertyInfos() {
+            desc += ", "
             desc += info.propertyKey + ": "
             if let propertyValue = value(forKey: info.propertyKey) {
                 desc += "\(propertyValue)"
             }
-            desc += ", "
         }
         return desc
     }
 
-    //convert Model to JSON object
+    /// convert Model to JSON object
     open func json() -> [String: Any] {
         var dictionary = [String: Any]()
         for info in type(of: self).propertyInfos() {

        return nil
    }
    
    //extract property read-only attribute
    private static func extractPropertyAttributeReadOnly(from string: String) -> Bool {
        // read-only format: R
        if let char = string.characters.first, char == "R" {

        var jsonKey = ""
        var attributes = PropertyAttributes()
    }

    /// map property key name to JSON key name
    open class var propertyKeyMapper: [String: String]? {
        return nil
    }

    /// If collection property which contain objects of Model Type, such as [Model], [String: Model]
    /// property name and its class type MUST be provided:
    open class var modelCollectionProperties: [String: Model.Type] {
        return [:]
    }
    
    /// convenience to create an array of Model from JSON
    public class func array(json: Any?) -> [Model] {
        return [Model](json: json, constructor: { (json) -> Model? in
            return self.init(json: json)
        })
    }

    /// convenience to create a dictionary with Model as value from JSON
    public class func dictionary(json: Any?) -> [String: Model] {
        return [String: Model](json: json, constructor: { (json) -> Model? in
            return self.init(json: json)
        })
    }
    
    /// convenience to get property key's according json key
    class func jsonKey(_ propertyKey: String) -> String {
        return propertyKeyMapper?[propertyKey] ?? propertyKey
    }
    
    /// for performance, introspect model property info only once, cache them to reuse
    private static var cachedAllModelPropertyInfos: [String: [PropertyInfo]] = [:]
    
    /// extract property type from attribute string
    private static func extractPropertyAttributeType(from string: String) -> AnyClass? {
        // type string format: @"ClassName", B, q, f
        if let char = string.characters.first, char == "@" {
