我正在尝试使用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'} ],
(文件的其他部分扩展良好)
所以,这是一个问题:有没有办法让它按照我的需要运作? ......或者我应该在服务器端制作技巧(正如我现在所做的那样)...
提前致谢。
答案 0 :(得分:3)
你有两个选择:
无论如何,两种方式都使用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;
}
});