2011-12-09 61 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