ExtJS 4编写器用于嵌套带有数组的JSON

时间:2014-03-25 15:05:00

标签: javascript arrays json extjs4 writer

我正在尝试使用ExtJS4处理嵌套结构的JSON。请不要像here那样回答 因为这是错误的答案。我使用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'} ],

(文件的其他部分扩展良好)

所以,这是一个问题:有没有办法让它按照我的需要运作? ......或者我应该在服务器端制作技巧(正如我现在所做的那样)...

提前致谢。

2 个答案:

答案 0 :(得分:3)

你有两个选择:

  • 正确的方法,即使用商店功能:定义你的dataWriter并编写你自己的函数,以获得你想要的json。
  • 不要使用商店更新记录,创建所需的json,并使用Ajax请求更新需要更新的记录。

无论如何,两种方式都使用Ajax,第一种应该是首选。

我会将我的作家定义在与商店相同的文件中,例如:

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定义的对象。但这是一个不同的问题。

答案 1 :(得分:0)

我已经使用了上面的答案,但是想要分享代码,以便让那些尝试同样事情的人更容易。

博士。上面的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;
    }
});