[英]GSON : custom object deserialization
好的,所以我編輯了這個問題因為它不夠清楚。
編輯2 :更新了JSON文件。
我在Android應用程序中使用GSON,我需要解析來自服務器的JSON文件,並且有點過於復雜。 我不希望我的對象結構太重,所以我想簡化內容: 所以我的對象的結構將不是JSON文件的結構。
例如,如果在JSON中我有這個:
{
"object1":{
"attribute1" : "test1",
"attribute40" : "test40",
"user":{
"id":1,
"name":"foo"
}
,"example":{
"total":10,
"list":[
{
"tag":"tag1",
"name":"object name 1",
"pos":1
},
{
"tag":"tag10",
"name":"object name 10",
"pos":10
}
]
}
}
"object2":{
"attribute1":"test..."
}
}
我不想保留我當前的對象結構,一個對象Example
,它包含一個ArrayList
和一個int
“total”。 但我想只保留一個簡單的String,其值為"object name 1;object name 2;..."
。
此外,我想只存儲用戶ID,而不是完整的用戶,因為我已經將完整的用戶存儲在其他地方,並且還有其他服務器API調用。
所以我的班級類似於:
class Foo{
int userId;
String example; //"object name 1;object name 2;..."
...
}
所以我想我們可以使用自定義反序列化器實現這一點,但我找不到如何。 我想盡可能減少內存,所以我不認為有一個完整的對象示例,然后使用它來構建我的String example
是一種正確的方法。
在最壞的情況下,如果它太復雜,我希望能夠在解析示例對象時至少只存儲Tag項列表:所以我需要一個自定義反序列化器來擺脫int total
。
所以我會:
class Foo{
int userId;
ArrayList<Tag> example;
...
}
我采用了答案來呈現聊天中設計的完整解決方案,以適應更改的JSON字符串。 該代碼假定字符串json完全包含問題中的(更新的)JSON。 要求是填寫以下類(setter和toString ommitted):
class Object1
{
private String attribute1;
private String attribute40;
private int userId;
private String nameList;
}
GSON支持(作為大多數其他REST-libs)三種模式:
JsonParser.parse()
讀取整個JSON,並在內存中構建DOM樹(對象模型訪問)。 因此,此解決方案適用於小型JSON文件。 JsonReader
只讀取JSON的塊。 代碼更復雜,但它適用於大型JSON文件。 從Android 3.0 Honeycomb開始,GSON的流解析器包含在android.util.JsonReader
。 要通過GSON_DOM和GSON_BIND填充Object1類,實現如下:
private static void deserializeViaObjectAccess(final String json)
{
Gson gson = new Gson();
// Read the whole JSON into meomory via GSON_DOM
JsonParser parser = new JsonParser();
JsonObject object1 = parser.parse(json).getAsJsonObject().getAsJsonObject("object1");
// map the Object1 class via GSON_BIND
// (bind common attributes which exist in JSON and as properties in the class)
// mapper acts as factory
Object1 result = gson.fromJson(object1, Object1.class);
// manually read the attribute from the user object
int userId = object1.getAsJsonObject("user").getAsJsonPrimitive("id").getAsInt();
result.setUserId(userId);
// manually read the attributes from the example object
String names = "";
JsonArray list = object1.getAsJsonObject("example").getAsJsonArray("list");
for (int i = 0; i < list.size(); ++i)
{
JsonObject entry = list.get(i).getAsJsonObject();
String name = entry.getAsJsonPrimitive("name").getAsString();
names = i == 0 ? name : names + "; " + name;
}
result.setNameList(names);
// Output the result
log.debug(result.toString());
}
要通過GSON_STREAM和GSON_BIND填充Object1類,實現如下:
目前,這只有在通過GSON_BIND或GSON_STREAM完全加載節點時才有可能。 此示例需要分割節點本身。 這僅適用於即將推出的2.2版本。 稍后我會在GSON 2.2可用時提交代碼。*
其中一個選項是解析使用內部GSON內置詳見解析器JSON字符串這里 。 你會做這樣的事情:
com.google.gson.JsonParser parser = new JsonParser();
JsonObject object = parser.parse(data).getAsJsonObject();
JsonObject example = object.getAsJsonObject("example");
JsonArray list = example.getAsJsonArray("list");
JsonObject和JsonArray是Gson本身的一部分。
使用這些之后,您可以使用getAsInt等函數來解析單個字段,並構建並返回您想要的任何對象。
編輯1
看起來你也可以在自定義類上使用gson.fromJson而不僅僅是本例中給出的通用Java類型。 因此,您必須使用parse解析JSON字符串,並在其中一個內部對象或數組上調用fromJson。
將示例JSON序列化為完整的Example對象,使用Example對象的name屬性構建所需事物的String,忘記Example對象。
我並不完全理解第二個問題,但如果你有一個完整的Test1對象將所有的字段/屬性,那么你可以創建一個Test2對象,它從Test1獲取它想要的字段。 例如,您的Test2對象可以在其構造函數中接受Test1作為參數,並僅采用它忽略其余部分所需的屬性。
當您通過http在Jsons中進行流式傳輸時,您可以簡單地丟棄文本並僅存儲自定義對象。 在這種情況下,您將不斷丟棄不需要的信息。
While stream not empty
Read the next block into a new string
Deserialize the string to the your object
Store the object in a myArrayList
注意:如果您希望應用程序具有可靠性,則讀取整個JSON並將其作為一個整體使用是非常必要的。 除非您想將JSON讀作原始字符流(我懷疑,除非您的JSON真的非常大,否則這個快捷方式是必要的)。
Neverthelss,讀取輸入流而不強加和JSON良好構造要求,可以在不必編寫和不必要的數據結構到內存的情況下完成。 如果您只想要一小部分數據,這可能會有效 - 即您只需要人們的名字或JSON中的網址。 但如果您想要更復雜的數據結構,它就會崩潰。 不過:
//示例解析來自JSON行的URL而不存儲整個數據結構
While input stream is not empty
String x = nextLine
If x contains "http"
myArrayList.add(parseUrl(x)
最后的想法 :
Bur最終,Jsons REST請求不像SQL那樣 - 你不能在通用和任意地忽略某些領域。也許,如果你真的想要更輕量級的Jsons,更自然的方法是告訴或檢查你的RESt服務提供商是否可以簡單地擴大類型RESt請求參數以適應您的用例。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.