【问题标题】:ExtJS 4 writer for nested JSON with array用于嵌套 JSON 的 ExtJS 4 编写器与数组
【发布时间】:2014-03-25 15:04:59
【问题描述】:

我正在尝试使用 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"
              }
            }
          }
        ]
        ...

但我不能让 writer 解析行。当我想保存我的文档时,我已经有这样的输出:

{ lines: 
   [ { line_lineItem_lineNumber: 1,
       line_lineItem_ean: '4352345234523',
       line_lineItem_orderedQuantity: '45'} ],

(文档的其他部分展开得很好)

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

提前致谢。

【问题讨论】:

    标签: javascript arrays json extjs4 writer


    【解决方案1】:

    你有两个选择:

    • 正确的方法是使用stores功能:定义你的dataWriter并编写你自己的函数以获得你想要的json。
    • 不要使用 store 来更新你的记录,创建你想要的 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”,因为您已经在 line lineItem 和 lineItem 和对象之间建立了一对一的关系由 lineItem 定义。但这是一个不同的问题。

    【讨论】:

    • 嗨,@皮埃尔!感谢您的回答。与 lineItem 并不是真正的一对一,因为 line 元素内部和外部允许有许多可选元素(如 lineOrder、lineDelivery 内部和与 line 同级的本地化),所以,这不是错误,只是一个糟糕的例子:)...关于作家...覆盖getExpandedData函数不是更好吗?据我了解,这不能通过配置选项来完成?
    • 好的,感谢您的澄清。关于编写器:1)如果您覆盖,它将为您将在应用程序中使用的每个编写器这样做,因此在这种情况下更喜欢继承 2)getExpandedData 受到保护。明智的 JavaScript 并没有什么不同,但请尝试将其视为您无法真正使用的私有 API。它可能会改变并且不会在公共方法所在的地方被弃用。
    • 所以,这行得通!这是最终解决方案:1)作为一个非常懒惰的人,我刚刚将 getExpandedData 从 ext-all-debug.js 复制到了我的自定义编写器的 getRecordData 2)进行了一些更正:a)向开始 if(!Array.isArray(data)) data = [data.getData()]; b) 将 if (item.hasOwnProperty(prop)) 正文包裹到另一个 if 语句 if(Array.isArray(item[prop])) this.getRecordData(item[prop]); else ...body... c) 更改为 '.'到nameParts = prop.split('_') 中的'_' 所以,非常感谢你展示了正确的方式......我相信他们应该将它作为一个功能添加到 ExtJS 中:)
    【解决方案2】:

    我已经使用了上面的答案,但想分享代码以使尝试相同事情的人更容易。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多