Javascript 带数组的嵌套JSON的ExtJS 4编写器

Javascript 带数组的嵌套JSON的ExtJS 4编写器,javascript,arrays,json,extjs4,writer,Javascript,Arrays,Json,Extjs4,Writer,我试图用ExtJS4处理嵌套结构的JSON。请不要这样回答 因为这是错误的答案。我在模型映射中使用了expandData:true,它非常适合我 我认为问题在于一个字段是对象数组。下面是我的代码示例: Ext.define('EdiWebUI.model.Document', { extend: 'Ext.data.Model', fields: [ {name: 'document_header_documentReceiveDateTime', mapping: 'docum

我试图用ExtJS4处理嵌套结构的JSON。请不要这样回答 因为这是错误的答案。我在模型映射中使用了
expandData:true
,它非常适合我

我认为问题在于一个字段是对象数组。下面是我的代码示例:

Ext.define('EdiWebUI.model.Document', {
  extend: 'Ext.data.Model',
  fields: [
    {name: 'document_header_documentReceiveDateTime', mapping: 'document.header.documentReceiveDateTime', type: 'string'},
    {name: 'document_header_documentProcessDateTime', mapping: 'document.header.documentProcessDateTime', type: 'string'},
    {name: 'document_header_documentID', mapping: 'document.header.documentID', type: 'string'},
    ...
    {name: 'lines', type: 'auto'},
    ...
    {name: 'attachments_documentFile_fileName', mapping: 'attachments.documentFile.fileName', type: 'string'},
    {name: 'attachments_documentFile_content', mapping: 'attachments.documentFile.content', type: 'string'}
  ],
  hasMany: [
    {model: 'DocumentLines', name: 'lines', associationKey: 'lines'}
  ],
  proxy: {
    type: 'rest',
    url: '/document',
    reader: {
      type: 'json',
      root: 'data'
    },
    writer: {
      expandData: true,
      writeAllFields: true,
      nameProperty: 'mapping'
    }
  }
});

Ext.define('DocumentLines',{
  extend: 'Ext.data.Model',
  fields: [
    {'name': 'line_lineItem_lineNumber', mapping: 'line.lineItem.lineNumber', type: 'string'},
    {'name': 'line_lineItem_orderedQuantity', mapping: 'line.lineItem.orderedQuantity', type: 'string'},
    {'name': 'line_lineItem_orderedUnitPackSize', mapping: 'line.lineItem.orderedUnitPackSize', type: 'string'},
    ...
});
因此,在阅读JSON时,它工作得很好,如下所示:

{
  "data": {
    "document": {
      "header": {
        "documentReceiveDateTime": "2014-03-25T08:34:24",
        "documentProcessDateTime": "2014-03-25T08:44:51",
        "documentID": "83701540",
        ...,
        "lines": [
          {
            "line": {
              "lineItem": {
                "lineNumber": "1",
                "orderedQuantity": "5.000",
                "orderedUnitPackSize": "1.000"
              }
            }
          },
          {
            "line": {
              "lineItem": {
                "lineNumber": "2",
                "orderedQuantity": "4.000",
                "orderedUnitPackSize": "1.000"
              }
            }
          }
        ]
        ...
{ lines: 
   [ { line_lineItem_lineNumber: 1,
       line_lineItem_ean: '4352345234523',
       line_lineItem_orderedQuantity: '45'} ],
但我不能让writer解析行。当我尝试保存文档时,我已经有如下输出:

{
  "data": {
    "document": {
      "header": {
        "documentReceiveDateTime": "2014-03-25T08:34:24",
        "documentProcessDateTime": "2014-03-25T08:44:51",
        "documentID": "83701540",
        ...,
        "lines": [
          {
            "line": {
              "lineItem": {
                "lineNumber": "1",
                "orderedQuantity": "5.000",
                "orderedUnitPackSize": "1.000"
              }
            }
          },
          {
            "line": {
              "lineItem": {
                "lineNumber": "2",
                "orderedQuantity": "4.000",
                "orderedUnitPackSize": "1.000"
              }
            }
          }
        ]
        ...
{ lines: 
   [ { line_lineItem_lineNumber: 1,
       line_lineItem_ean: '4352345234523',
       line_lineItem_orderedQuantity: '45'} ],
(文件的其他部分展开得很好)

所以,这里有一个问题:有没有办法让它按我的需要工作? …或者我应该在服务器端玩个把戏(就像我现在实际做的那样)


提前感谢。

您有两个选择:

  • 正确的方法是使用stores功能:定义dataWriter并编写自己的函数,以获得所需的json
  • 不要使用存储来更新记录,而是创建所需的json,并使用Ajax请求更新需要更新的记录
不管怎样,两种方法都使用Ajax,应该首选第一种

我将在与存储相同的文件中定义我的writer,类似于:

Ext.define('MyApp.custom.Writer',{
    /*
     * Formats the data for each record before sending it to the server. 
     * This method should be overridden to format the data in a way that differs from the default.
     */
    getRecordData: function(record) {
        var data = {};
        /*
         * Parse your record and give it whatever structure you need here..
         */
        data.lines = [];
        return data;
    }
});

尽管Json中似乎有一个额外的间接级别,但不需要“lineItem”,因为lineItem和lineItem与lineItem定义的对象之间已经存在一对一的关系。但这是一个不同的问题

我已经使用了上面的答案,但我想与大家分享代码,让尝试同样方法的人更容易一点

Leevsey博士上面的代码对我来说很有效,但它的缺点是它将所有东西都放在一个数组中。对于我的项目来说,如果它返回一个对象(包含子对象),而如果基本对象不是数组,则不返回数组,效果会更好

代码如下:

Ext.define('MyApp.util.customWriter',
{
    extend: 'Ext.data.writer.Json',
    getRecordData: function (record, operation) {
        var data = record;
        var me = this;
        var toObject = function (name, value) {
            var o = {};
            o[name] = value;
            return o;
        };
        var itemsToObject = function (item) {
            for (prop in item) {
                if (Array.isArray(item[prop])) {
                    me.getRecordData(item[prop]);
                }
                else {
                    if (item.hasOwnProperty(prop)) {
                        var nameParts = prop.split('.');
                        var j = nameParts.length - 1;
                        if (j > 0) {
                            var tempObj = item[prop];
                            for (; j > 0; j--) {
                                tempObj = me.toObject(nameParts[j], tempObj);
                            }
                            item[nameParts[0]] = item[nameParts[0]] || {};
                            Ext.Object.merge(item[nameParts[0]], tempObj);
                            delete item[prop];
                        }
                    }
                }
            }
        };

        if (!Array.isArray(data)) {
            data = data.getData();
            itemsToObject(data);
        }
        else {
            var dataLength = data.length;
            for (var i = 0; i < dataLength; i++) {
                itemsToObject(data[i]);
            }
        }

        return data;
    }
});
Ext.define('MyApp.util.customWriter',
{
扩展:“Ext.data.writer.Json”,
getRecordData:函数(记录、操作){
var数据=记录;
var me=这个;
var toObject=函数(名称、值){
var o={};
o[名称]=值;
返回o;
};
var itemsToObject=函数(项){
用于(项目中的道具){
if(Array.isArray(项[prop])){
me.getRecordData(项目[prop]);
}
否则{
if(项目hasOwnProperty(道具)){
变量nameParts=prop.split('.');
var j=nameParts.length-1;
如果(j>0){
var tempObj=项目[prop];
对于(;j>0;j--){
tempObj=me.toObject(nameParts[j],tempObj);
}
item[nameParts[0]]=item[nameParts[0]]| |{};
Ext.Object.merge(项[nameParts[0]],tempObj);
删除项目[prop];
}
}
}
}
};
如果(!Array.isArray(数据)){
data=data.getData();
项目对象(数据);
}
否则{
var dataLength=data.length;
对于(变量i=0;i
你好,@Pierre!谢谢你的回答。这并不是一对一的lineItem,因为在line元素的内部和外部都允许有许多可选元素(如lineOrder、lineDelivery in line和与line处于同一级别的本地化),所以,这不是一个错误,只是一个糟糕的例子:)…关于一个writer。。。重写函数不是更好吗?据我所知,这不能通过配置选项完成?好的,谢谢你的澄清。关于writer:1)如果覆盖,则应用程序中使用的每个writer都会覆盖,因此在本例中首选继承2)getExpandedData受到保护。就JavaScript而言,这没有什么区别,但试着将其视为一个您无法真正使用的私有API。它可能会更改,并且不会在公共方法所在的位置被弃用。所以,这是可行的!这里有一个最终的解决方案:1)作为一个非常懒惰的人,我刚刚将
getExpandedData
从ext-all-debug.js复制到我的定制writer的
getRecordData
。2)做了一些更正:a)在开头添加了新条件
if(!Array.isArray(data))data=[data.getData()]b)将if(item.hasOwnProperty(prop))包装到另一个if语句中
if(Array.isArray(item[prop])这个.getRecordData(item[prop]);否则…body…
c)在
nameParts=prop.split(“”“)
中将“.”更改为“uu”,因此,非常感谢您展示了正确的方法…我认为他们应该在ExtJS中添加它作为一项功能:)