2011-04-19 47 views
3

我正在使用JsonReader将Json数据映射到要在网格/表单中使用的变量。后端是Java,并且有一些复杂的对象,我将它们传递给ExtJS前端。 这是我JsonReader的一部分,它试图获取一个嵌套的对象 -ExtJS - 使用JsonReader对复杂对象进行null安全检索

{name:'status', type: 'string', mapping: 'status.name'} 

能正常工作状态时有一个值(在服务器不为空),但是当状态是空的电网负荷失败。目前我所做的工作是在发送null的情况下从服务器发送一个空对象,但我认为应该有一种方法可以在ExtJS中处理这个问题。请在ExtJS方面提出更好的解决方案。

+0

你是否已经精确地定位错误发生在哪里? (例如,切换到'ext-all-debug.js'并使用Firebug) – Tommi 2011-04-19 05:40:38

+0

@Tommi这是因为状态是未定义的,并且'JsonReader'试图使用'status.name'来提取数据,它是,'undefined.name'。 – 2011-04-19 06:18:06

+0

@Lionel Chan是的我明白,但是我问是否知道在哪里(在ExtJS代码中)恰恰会导致“网格加载失败”。 – Tommi 2011-04-19 07:29:57

回答

4

我能想到的两种可能性 - 一个记录,一个无证:

  1. 使用convert() -mechanism的Ext.data.Field

    { 
        name:'status', 
        mapping: 'status', 
        convert: function(status, data) { 
         if (!Ext.isEmpty(status) && status.name) { 
          return status.name; 
         } else { 
          return null; 
         } 
        } 
    } 
    
  2. mapping属性还可以参加抽取函数(这是没有记录的,所以依靠这可能有点冒险):

    { 
        name:'status', 
        mapping: function(data) { 
         if (data.status && data.status.name) { 
          return data.status.name; 
         } else { 
          return null; 
         } 
        } 
    } 
    
0

使用此安全JSON读者,而不是:

Ext.define('Ext.data.reader.SafeJson', { 
extend: 'Ext.data.reader.Json', 
alias : 'reader.safe', 
/** 
* @private 
* Returns an accessor function for the given property string. Gives support for properties such as the following: 
* 'someProperty' 
* 'some.property' 
* 'some["property"]' 
* This is used by buildExtractors to create optimized extractor functions when casting raw data into model instances. 
*/ 
createAccessor: function() { 
    var re = /[\[\.]/; 

    return function(expr) { 
     if (Ext.isEmpty(expr)) { 
      return Ext.emptyFn; 
     } 
     if (Ext.isFunction(expr)) { 
      return expr; 
     } 
     if (this.useSimpleAccessors !== true) { 
      var i = String(expr).search(re); 
      if (i >= 0) { 

       if (i > 0) { // Check all property chain for existence. Return null if any level does not exist. 
        var a = []; 
        var l = expr.split('.'); 
        var r = ''; 
        for (var w in l) { 
         r = r + '.' + l[w]; 
         a.push('obj' + r); 
        } 
        var v = "(" + a.join(" && ") + ") ? obj." + expr + " : null"; 
        return Ext.functionFactory('obj', 'return (' + v + ')'); 
       } else { 
        return Ext.functionFactory('obj', 'return obj' + expr); 
       } 
      } 
     } 
     return function(obj) { 
      return obj[expr]; 
     }; 
    }; 
}() 
}); 
0

我已经改变斯拉瓦Nadvorny的例子,使其完全适用于ExtJS的4.1.1。

新扩展的类Ext.data.reader.Json的低于:

Ext.define('Ext.data.reader.SafeJson', { 
    extend: 'Ext.data.reader.Json', 
    alias : 'reader.safejson', 
    /** 
    * @private 
    * Returns an accessor function for the given property string. Gives support for properties such as the following: 
    * 'someProperty' 
    * 'some.property' 
    * 'some["property"]' 
    * This is used by buildExtractors to create optimized extractor functions when casting raw data into model instances. 
    */ 
    createAccessor: (function() { 
     var re = /[\[\.]/; 

     return function(expr) { 
      if (Ext.isEmpty(expr)) { 
       return Ext.emptyFn; 
      } 
      if (Ext.isFunction(expr)) { 
       return expr; 
      } 
      if (this.useSimpleAccessors !== true) { 
       var i = String(expr).search(re); 
       if (i >= 0) { 
        if (i > 0) { // Check all property chain for existence. Return null if any level does not exist. 
         var a = []; 
         var l = expr.split('.'); 
         var r = ''; 
         for (var w in l) { 
          r = r + '.' + l[w]; 
          a.push('obj' + r); 
         } 
         var v = "(" + a.join(" && ") + ") ? obj." + expr + " : null"; 
         return Ext.functionFactory('obj', 'return (' + v + ')'); 
        } else { 
         return Ext.functionFactory('obj', 'return obj' + (i > 0 ? '.' : '') + expr); 
        } 
       } 
      } 
      return function(obj) { 
       return obj[expr]; 
      }; 
     }; 
    }()), 

     /** 
    * @private 
    * @method 
    * Returns an accessor expression for the passed Field. Gives support for properties such as the following: 
    * 
    * - 'someProperty' 
    * - 'some.property' 
    * - 'some["property"]' 
    * 
    * This is used by buildExtractors to create optimized on extractor function which converts raw data into model instances. 
    */ 
    createFieldAccessExpression: (function() { 
     var re = /[\[\.]/; 

     return function(field, fieldVarName, dataName) { 
      var me  = this, 
       hasMap = (field.mapping !== null), 
       map = hasMap ? field.mapping : field.name, 
       result, 
       operatorSearch; 

      if (typeof map === 'function') { 
       result = fieldVarName + '.mapping(' + dataName + ', this)'; 
      } else if (this.useSimpleAccessors === true || ((operatorSearch = String(map).search(re)) < 0)) { 
       if (!hasMap || isNaN(map)) { 
        // If we don't provide a mapping, we may have a field name that is numeric 
        map = '"' + map + '"'; 
       } 
       result = dataName + "[" + map + "]"; 
      } else {     
       if (operatorSearch > 0) { 
        var a = []; 
        var l = map.split('.'); 
        var r = ''; 
        for (var w in l) { 
         r = r + '.' + l[w]; 
         a.push(dataName + r); 
        } 
        result = "("+a.join(" && ")+") ? "+dataName+"."+map+" : null"; 
       } else { 
        result = dataName + map; 
       } 
      }    
      return result; 
     }; 
    }()) 
}); 

这样你就可以成功地处理嵌套的JSON数据与空节点。 JSON的

例子:

{ 
    root: [{ 
     id: 1, 
     name: { 
      name: "John", 
      phone: "123" 
     },   
    }, 
    { 
     id: 4, 
     name: null,   
    }, 
    ] 
} 

工作实例与测试数据,你可以在这里找到: http://jsfiddle.net/8Ftag/

+0

感谢您的支持!由于生成的测试不是类型安全的,因此必须进行微调,因为'0'(零)值返回为null。我通过更改连接方法来修复它,以便用Ext.isEmpty()包装路径中的每个字段... result ='(!Ext.isEmpty('+ a.join(')&&!Ext.isEmpty(' )+'))? '+ dataName +'。' + map +':null'; – JamieB 2012-11-29 14:23:19