2011-12-09 73 views
4

我在Android代碼中遇到一個奇怪的問題,當我試圖將Json-smart JSONObjectJSONArray作爲可序列化數據傳遞給Intent serializable extra時。 Json-smart是非常快速和精益的JSON解析器實現,我強烈推薦它。 JSONObject延伸HashMap<String, Object>JSONArray延伸ArrayList<Object>與很少的開銷。這些對象的虛空覆蓋Object#writeObject#readAndroid - json-smart反序列化問題

這裏的問題:

如果我用說Fragment#onSaveInstanceState(String, JSONObject)一切工作就好了這些對象。如果我在普通的Java示例項目中序列化/反序列化這些對象,它再次按預期工作。但是,如果我用Intent#putExtra(String, JSONObject),然後嘗試做

JSONObject json = (JSONObject) intent.getSerializableExtra("JSON"); 

讓我的JSONObject我會得到ClassCastException因爲什麼方法返回的是一個普通的HashMap(JSONArray,並在情況下,它的ArrayList)。此外,如果我看地圖/陣列中的內容被完全剝離到的JSONObject/JSONArray任何引用,幷包含HashMap /的ArrayList

filed the ticket更換和提供的示例項目,但遺憾的是筆者關閉了它,但未得到解決,所以我乾脆試圖達到它的底部。如果你去的票,它有簡單的項目附加。

有沒有辦法呢?現在我要的JSONObject或JSONArray轉換爲字符串,並重新分析這回對象,如:

JSONArray feeds = (JSONArray) JSONValue.parse(intent.getStringExtra(RAW_FEED)); 
+1

fyi,'JSONObject json = new JSONObject(intent.getSerializableExtra(「JSON」))'應該只是花花公子。 – Jens

+0

@Jens這不起作用(至少完全)。是的 - 你會得到外部JSONObject,但所有內部結構將是純HashMaps和ArrayLists。我只是通過修改和執行門票 – Bostone

+0

中包含的測試項目來驗證這一點。 JSON對象可以從HashMap構建,實際上是一個HashMap。 –

回答

3

實施android.os.Parcelable:

http://developer.android.com/reference/android/os/Parcelable.html 

基本上,你把一點點額外的編碼到你的對象中來解釋如何序列化和反序列化它。這就是爲什麼它丟失了你的課程信息,它不知道如何正確地序列化它。如果我是你,我會通過你的意圖傳遞一個JSON對象的值對象,因爲知道你確切地知道你傳遞了什麼類型的對象。您找回您的Parcelable這樣:

getIntent().getExtras().getParcelable(key); 

我知道這可能看起來一點額外的代碼,但實際上,我認爲這是分享活動之間數據的漂亮乾淨的方式。你正在傳遞一個強大的類型,你指定了如何壓縮/膨脹它,你的活動並不需要彼此有任何工作知識。

在你的價值對象,你只需填寫這樣的空白:

/** Parcelable implementation: deserialize object 
* @param in Parcel object containing the data for this object 
* @return a Person object */ 
public Person(Parcel in) { 
    String[] data = new String[2]; 
    in.readStringArray(data); 
    this.firstName = data[0]; 
    this.lastName = data[1]; 
} 

/** Parcelable implementation code */ 
public int describeContents() { 
    return 0; 
} 

/** Parcelable implementation: Serialize object to be passed between activities via Intent 
* @param dest The parcel to transport the object 
* @param flags refer to Parcelable api 
* @return nothing */ 
public void writeToParcel(Parcel dest, int flags) { 
    dest.writeStringArray(new String[] { 
      this.firstName, 
      this.lastName,  
    }); 
} 

希望這有助於,可能會多一點的代碼比你要找的,但它是一個真正乾淨的解決方案,因爲當目標活動獲取對象,您不必擔心反序列化,這意味着您的活動中的代碼更乾淨。脂肪模型,乾淨的意見:)

+0

我試圖不擴充JSON對象,但使用「原樣」。我對反序列化問題感到困惑,並且想明白爲什麼Android會在這種情況下去掉對象類型 – Bostone

+0

當你實現Parcelable時,你告訴Android如何序列化和反序列化你的對象而不會丟失任何信息,比如類型。這就是你的問題所在,當你傳遞JSONObject,這是一個類,就像我的Person例子一樣,Android不知道如何處理它。如果您想要通用方式來傳遞JSON對象,請嘗試創建一個值對象,該對象具有一個類型爲JSONObject的屬性以用於有效內容。在該值對象上實現Parcelable。這會給你一個傳送對象來發送你的JSON對象。更多的設計建議,但它應該工作:) – jerrylroberts

+0

我不確定這樣做會比轉換/解析純字符串 – Bostone

1

作爲一個JSON對象隱式是一個字符串,爲什麼不把它傳遞爲字符串?

// save the json string 
JSONObject json = ... 
intent.putExtra("json", json.toString()); 


// Let's read it in in the next activity 
JSONObject json = new JSONObject(intent.getExtra("json")); 
+0

這就是我所做的。但是,這需要重新解析字符串對象,並且令人驚訝地昂貴 – Bostone

+0

並且也看到我的答案(對於我自己的問題) – Bostone

0

如果你讀這篇文章,不知道哪種解決方案,我終於實現我意識到,我可以高興地使用基於地圖/ List對象的精簡版本,因爲它保留了結構和所有按鍵。沒有必要猴子與Parcelable