Java 使用包含ArrayList的HashMap初始化的JSONObject在某些Android 4版本上初始化不正确-如何修复它? 上下文
使用Couchbase Lite()加载json文档的Android应用程序。例如,包含问题列表的问卷:Java 使用包含ArrayList的HashMap初始化的JSONObject在某些Android 4版本上初始化不正确-如何修复它? 上下文,java,android,json,couchbase-lite,Java,Android,Json,Couchbase Lite,使用Couchbase Lite()加载json文档的Android应用程序。例如,包含问题列表的问卷: { "questions": [ { "answer": 1, "attributeName": "baiOne", "text": "Some text", "timeOfAnswer": { "timezoneOffset": -60,
{
"questions": [
{
"answer": 1,
"attributeName": "baiOne",
"text": "Some text",
"timeOfAnswer": {
"timezoneOffset": -60,
"utcTime": 1458118338993
}
},
...
],
"endDate": 1458604800000,
"startDate": 1458086400000,
"title": "BAI"
}
这是正确加载的
Document doc = database.getDocument(docId);
Map<String, Object> props =
new HashMap<String, Object>(doc.getProperties());
问题
好的,让我们跳到麻烦制造者:
JSONObject结果=新JSONObject(道具)
在Android 4.4.2(api级别19)及更高版本上,它看起来是正确的:
- 结果JSONObject中的questions属性(ArrayList)作为JSONArray生成
- result.toString()被记录:
{“问题”:[{“答案”:1,“属性名称”:“baiOne”}]}
- 结果JSONObject中的questions属性(ArrayList)作为JSONObject生成
- result.toString()被记录:
其中整个问题块被转换成一个大字符串{“问题”:“[{attributeName=baiOne,answer=1}]”
- result.toString()被记录:
@Test
public void testRegression_hashmap_to_json_object()
throws JSONException, CouchbaseLiteException, IOException {
Log.v(TAG, "Create data that mimic a json document loaded from coucbase lite:");
Map<String, Object> question = new HashMap<String, Object>();
question.put("answer", 1);
question.put("attributeName", "baiOne");
List<Map<String, Object>> questions = new ArrayList<Map<String, Object>>();
questions.add(question);
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("questions", questions);
Log.v(TAG, "Create JSONObject from properties hashmap:");
JSONObject t = new JSONObject(properties);
// Do stuff with t ...
Log.v(TAG, "t.toString(): " + t.toString());
// prints on android 4.1.2 (16) - 4.3 (18) prints incorrectly:
// t.toString(): {"questions":"[{attributeName=baiOne, answer=1}]"}
// android 4.4.2 (19) and up prints correctly:
// t.toString(): {"questions":[{"answer":1,"attributeName":"baiOne"}]}
JSONArray a = t.getJSONArray("questions");
assertTrue(a != null);
assertTrue(a.length() == 1);
// Save doc back to couchbase lite
}
根据@Borrden和couchbase lite api/教程(例如)的反馈,解决方案是纯粹使用
new HashMap()
,而根本不使用JSONObject
。根据@Borrden和couchbase lite api/教程(例如)的反馈,解决方案是纯粹使用new HashMap()
并且根本不要使用JSONObject
。链接的问题似乎有解决方案。你试过了吗?@borrrden thx获得反馈!我应该在这篇文章中提到,另一篇文章中提到的解决方案并不能解决这个问题:在HashMap中作为值的ArrayList没有转换成JSONArray,这最终会导致toString不正确。此外,我不太喜欢引入af customjsonifier
…Couchbase Lite使用Java的Jackson序列化库。你可以试试。不过,我不确定这个问题是否与Couchbase Lite直接相关。@Borrden完美的建议!我也在沿着那条路往下看,但是当导入org.codehaus.jackson.map.ObjectMapper已经很晚了,因为它需要aJsonObject.toString()例如:Map props=new ObjectMapper().readValue(aJsonObject.toString(),HashMap.class)代码>除非我完全错过了api…重点是避免同时使用JSONObject,而是使用Jackson(实际上我不完全清楚这里的目标)。相关问题似乎有一个解决方案。你试过了吗?@borrrden thx获得反馈!我应该在这篇文章中提到,另一篇文章中提到的解决方案并不能解决这个问题:在HashMap中作为值的ArrayList没有转换成JSONArray,这最终会导致toString不正确。此外,我不太喜欢引入af customjsonifier
…Couchbase Lite使用Java的Jackson序列化库。你可以试试。不过,我不确定这个问题是否与Couchbase Lite直接相关。@Borrden完美的建议!我也在沿着那条路往下看,但是当导入org.codehaus.jackson.map.ObjectMapper
已经很晚了,因为它需要aJsonObject.toString()例如:Map props=new ObjectMapper().readValue(aJsonObject.toString(),HashMap.class)代码>除非我完全错过了api…重点是避免同时使用JSONObject,而是使用Jackson(实际上我并不完全清楚这里的目标)。
@Test
public void testRegression_hashmap_to_json_object()
throws JSONException, CouchbaseLiteException, IOException {
Log.v(TAG, "Create data that mimic a json document loaded from coucbase lite:");
Map<String, Object> question = new HashMap<String, Object>();
question.put("answer", 1);
question.put("attributeName", "baiOne");
List<Map<String, Object>> questions = new ArrayList<Map<String, Object>>();
questions.add(question);
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("questions", questions);
Log.v(TAG, "Create JSONObject from properties hashmap:");
JSONObject t = new JSONObject(properties);
// Do stuff with t ...
Log.v(TAG, "t.toString(): " + t.toString());
// prints on android 4.1.2 (16) - 4.3 (18) prints incorrectly:
// t.toString(): {"questions":"[{attributeName=baiOne, answer=1}]"}
// android 4.4.2 (19) and up prints correctly:
// t.toString(): {"questions":[{"answer":1,"attributeName":"baiOne"}]}
JSONArray a = t.getJSONArray("questions");
assertTrue(a != null);
assertTrue(a.length() == 1);
// Save doc back to couchbase lite
}
private JSONObject stringify(Map<String,Object> map) {
Map<String,Object> fixed = new HashMap<String,Object>();
for (String key : map.keySet()){
Object value = map.get(key);
if (value instanceof Map) {
value = stringify((Map<String,Object>) value);
}
if (value instanceof List) {
value = stringify(value);
}
fixed.put(key,value);
}
return new JSONObject(fixed);
}
private JSONArray stringify(Object value) {
JSONArray a = new JSONArray();
if (!((List) value).isEmpty() && ((List) value).get(0) instanceof Map) {
for (Map<String, Object> m: (List<Map<String, Object>>) value) {
a.put(stringify(m));
}
}
else {
for (Object m: (List<Object>) value) {
a.put(m);
}
}
return a;
}