我的問題很長...所以,請耐心等待:)如何忽略ExtJS數據模型中的空字段?
我正在使用ExtJS 4中的模型,但我在關聯中遇到了一些問題,所以我創建了一個函數來執行自動爲我創建模型。讓我們假設我需要分析以下JSON:
{
"success": true,
"total": 28,
"itens": [{
"id":1,
"nome":"ACRE",
"sigla":"AC",
"pais":{
"id":31,
"nome":"BRASIL",
"sigla":"BR"
}
},{
"id":2,
"nome":"ALAGOAS",
"sigla":"AL",
"pais":{
"id":31,
"nome":"BRASIL",
"sigla":"BR"
}
}, ...]
}
的itens代表各省(ESTADOS巴西葡萄牙語),其中有一個國家(巴西葡萄牙語國家報)。我試圖使用ExtJS關聯,但我認爲它像Java關係一樣工作,我錯了。那麼,對於這個JSON我有這些Java類和這些Ext模型(模型是使用提供的功能創建的)。
Pais.java
@Entity
// named queries here...
public class Pais implements Serializable {
@Id
@GeneratedValue
private Long id;
@NotNull
@NotEmpty
@Length(max = 100)
private String nome;
@NotNull
@NotEmpty
@Column(unique = true)
@Length(min = 2, max = 4)
private String sigla;
// getters, setters, equals, hashCode and toString here
}
Estado.java
@Entity
// named queries here...
public class Estado implements Serializable {
@Id
@GeneratedValue
private Long id;
@NotNull
@NotEmpty
@Length(max = 100)
private String nome;
@NotNull
@NotEmpty
@Column(unique = true)
@Length(min = 2, max = 4)
private String sigla;
@NotNull
@ManyToOne
private Pais pais;
// getters, setters, equals, hashCode and toString here
}
函數來創建模型
Ext.ns("Uteis");
// other utility functions here...
Uteis.createModel = function(modelData) {
var fields = modelData.fields;
var processedFields = [];
var normalFields = [];
var relationFields = [];
for (var i in fields) {
if (fields[i].type) {
switch (fields[i].type) {
case "auto":
case "string":
case "int":
case "float":
case "boolean":
case "date":
normalFields.push(fields[i]);
break;
default:
var relationField = fields[i];
var prefix = relationField.name + ".";
var modelInstance = Ext.create(relationField.type);
modelInstance.fields.each(function(item, index, length) {
var newField = {};
// I used this sintax to make possible create only some fields
// if I need in the future.
newField["name"] = prefix + item.name;
newField["type"] = item.type.type;
newField["convert"] = item.convert;
newField["dateFormat"] = item.dateFormat;
newField["defaultValue"] = item.defaultValue;
newField["mapping"] = item.mapping;
newField["persist"] = item.persist;
newField["sortDir"] = item.sortDir;
newField["sortType"] = item.sortType;
newField["useNull"] = item.useNull;
relationFields.push(newField);
});
break;
}
} else {
normalFields.push(fields[i]);
}
}
processedFields = normalFields.concat(relationFields);
// debugging code
/*console.log("*** " + modelData.name);
for (var i in processedFields) {
console.log(processedFields[i]);
}*/
Ext.define(modelData.name, {
extend: "Ext.data.Model",
fields: processedFields
});
};
使用函數來創建模型
Uteis.createModel({
name: "Modelos.Pais",
fields: [
{ name: "id", type: "int" },
{ name: "nome", type: "string" },
{ name: "sigla", type: "string" }
]
});
Uteis.createModel({
name: "Modelos.Estado",
fields: [
{ name: "id", type: "int" },
{ name: "nome", type: "string" },
{ name: "sigla", type: "string" },
{ name: "pais", type: "Modelos.Pais" } // <= references the model created above
]
});
上面的代碼對應了這一點。我創建了自動創建嵌套數據字段的功能(因爲我說的關聯問題)。
Ext.define("Modelos.Pais", {
extend: "Ext.data.Model",
fields: [
{ name: "id", type: "int" },
{ name: "nome", type: "string" },
{ name: "sigla", type: "string" }
]
});
Ext.define("Modelos.Estado", {
extend: "Ext.data.Model",
fields: [
{ name: "id", type: "int" },
{ name: "nome", type: "string" },
{ name: "sigla", type: "string" },
{ name: "pais.id", type: "int" },
{ name: "pais.nome", type: "string" },
{ name: "pais.sigla", type: "string" }
]
});
好的,這些模型(使用我的createModel函數創建)與我的JsonStores一起工作得很好。到目前爲止,Java方面的所有映射關聯都不爲null,因此,我的存儲總是有嵌套的數據進行處理。現在,我必須處理一些可能具有空關聯的實體,並且我的問題開始了。需要處理這種情況的商店不起作用(商店操作中引發了一個例外情況,稱這些字段爲空)。我使用Gson從我的實體創建JSON。它的默認行爲是不對空字段進行序列化,它們在客戶端是未定義的,所以如果我序列化null字段(發送null)會使Ext實現空字段而不嘗試處理它。要做到這一點,我用這個代碼來創建GSON:
Gson gson = new GsonBuilder().serializeNulls().create();
好了,現在正在生成與空協會JSON,但內線不斷抱怨。我試圖使用字段映射和defaultValue配置沒有成功。爲了使事情更簡單,我們使用Pais不是@NotNull的Estados和Países(Privinces and Countries)的例子。用空派斯的JSON會是這樣:
{
"success": true,
"total": 28,
"itens": [{
"id":1,
"nome":"ACRE",
"sigla":"AC",
"pais":null // <= here
},{
"id":2,
"nome":"ALAGOAS",
"sigla":"AL",
"pais":{ // this is not null
"id":31,
"nome":"BRASIL",
"sigla":"BR"
}
}, ...]
}
有了這個代碼,該pais.id,pais.nome和pais.sigla領域將不可用,因爲派斯屬性爲null。所以,我的問題是:如何使商店忽略某些字段爲空或未定義時?我已經試圖尋找一個沒有成功的解決方案......非常感謝!
編輯:在服務器端的一些可能的解決方案的思維了整個晚上之後,我實現了最後15分鐘的解決方案,但我definatelly不喜歡它...它遍歷每個物體反射的方法在使用Gson將默認值設置爲null的字段之前,使用「對象樹」。它正在工作,但JSON變得不必要的太大了。遍歷方法:
/**
* A method to traverse the object tree and set "default" values to null fields.
*
* @param target The object to be inspected.
*/
public static void traverseAndSetDefaultValue(Object target) {
try {
for (Field f : target.getClass().getDeclaredFields()) {
// ok to change...
f.setAccessible(true);
// is null? so create something
if (f.get(target) == null) {
// new instance of the current field
Object newInstance = null;
// it needs to traverse to the next level?
boolean okToTraverse = false;
switch (f.getType().getSimpleName()) {
case "Byte":
case "Short":
case "Integer":
newInstance = 0;
break;
case "Long":
newInstance = 0L;
break;
case "Float":
newInstance = 0F;
break;
case "Double":
newInstance = 0D;
break;
case "Character":
newInstance = '\0';
break;
case "Boolean":
newInstance = Boolean.FALSE;
break;
case "String":
newInstance = "";
break;
case "List":
newInstance = new ArrayList();
break;
case "Set":
newInstance = new HashSet();
break;
default:
// calling the default constructor for no
// "default" types
newInstance = f.getType().newInstance();
okToTraverse = true;
break;
}
f.set(target, newInstance);
if (okToTraverse) {
traverseAndSetDefaultValue(newInstance);
}
}
}
} catch (IllegalAccessException | InstantiationException exc) {
exc.printStackTrace();
}
}
我想你對它有什麼看法......謝謝! :再次問好。我放棄! :)我將使用我上面發佈的解決方案。我找到了some patches以改善與模型和網格的關係。我測試了它們,但空字段的問題仍然存在(至少錯誤消失了)。好的,現在是繼續發展的時候了。當應用程序完成後,我會回到這個問題來嘗試改進我的解決方案。謝謝!
我不知道有任何被具體問題使用模型數據中的空值,您可以粘貼'Uteis.createModel'函數的輸出,以便我們可以看到模型定義在運行後會是什麼樣子? 我認爲您需要確保您在模型上添加了與Ext'關聯'屬性的嵌套模型數據,但是我無法看到您的模型中是否存在您的函數。 – dougajmcdonald 2012-07-22 07:32:52
@dougajmcdonald:嗨。我也嘗試過,並在我的帖子中解釋過。當您嘗試在網格列中獲取嵌套值時,這些關聯無法使用null。該函數的輸出在兩個代碼snipets中的代碼下面列出。在第一次我展示了函數調用,第二次展示瞭如果使用Ext.define()並擴展Ext.data.Model時將生成的相應模型。 – davidbuzatto 2012-07-22 15:13:31
我認爲這是您問題的解決方案http://stackoverflow.com/a/12897584/1496088 – 2012-10-15 14:33:38