JsonObject toString() 输出键值对顺序研究,jsonobjecttostring
分享于 点击 16729 次 点评:213
JsonObject toString() 输出键值对顺序研究,jsonobjecttostring
背景
后台有一套接口,需要对传参进行排序,于是写了一套排序方法,在请求接口之前对所有参数排序,这里边用到了JsonObject及其自身的toString方法,测试过程中发现在一台android4.4系统的手机上程序运行不是预期结果,于是有了下面的研究
经过分析发现,问题出现的原因是JsonObject toString输出的键值对顺序不是固定的,并不是一定按照我们put元素进入的顺序输出,所以导致后面传递参数的顺序出了问题,下面看一下为什么object.toString输出顺序不固定
JsonObject部分源码如下:
public JSONObject() {
nameValuePairs = new HashMap<String, Object>();
}
public JSONObject put(String name, Object value) throws JSONException {
if (value == null) {
nameValuePairs.remove(name);
return this;
}
if (value instanceof Number) {
// deviate from the original by checking all Numbers, not just floats & doubles
JSON.checkDouble(((Number) value).doubleValue());
}
nameValuePairs.put(checkName(name), value);
return this;
}
我们发现,JsonObject中存储数据用的是HashMap,而HashMap并不是顺序存储数据的。
这时要想让object.toString输出的顺序,就需要自定义一个JsonObject,使用有序的LinkedHashMap代替无序的HashMap来进行数据存储
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONStringer;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
public class LinkedJsonObject extends JSONObject {
private LinkedHashMap<Object, Object> nameValuePairs;
public LinkedJsonObject() {
nameValuePairs = new LinkedHashMap<>();
}
@Override
public JSONObject put(String name, int value) throws JSONException {
return put(name, value);
}
@Override
public JSONObject put(String name, long value) throws JSONException {
return put(name, value);
}
@Override
public JSONObject put(String name, double value) throws JSONException {
return put(name, value);
}
@Override
public JSONObject put(String name, boolean value) throws JSONException {
return put(name, value);
}
@Override
public JSONObject put(String name, Object value) throws JSONException {
checkName(name);
if (value == null) {
nameValuePairs.remove(name);
return this;
}
if (value instanceof Double) {
if (((Double) value).isInfinite() || ((Double) value).isNaN()) {
throw new JSONException("JSON does not allow non-finite numbers.");
}
} else if (value instanceof Float) {
if (((Float) value).isInfinite() || ((Float) value).isNaN()) {
throw new JSONException("JSON does not allow non-finite numbers.");
}
}
nameValuePairs.put(name, value);
return this;
}
String checkName(String name) throws JSONException {
if (name == null) {
throw new JSONException("Names must be non-null");
}
return name;
}
public String toString() {
try {
Iterator<Object> keys = nameValuePairs.keySet().iterator();
StringBuffer sb = new StringBuffer("{");
while (keys.hasNext()) {
if (sb.length() > 1) {
sb.append(',');
}
Object o = keys.next();
sb.append(quote(o.toString()));
sb.append(':');
sb.append(valueToString(nameValuePairs.get(o)));
}
sb.append('}');
return sb.toString();
} catch (Exception e) {
return null;
}
}
static String valueToString(Object value) throws JSONException {
if (value == null || value.equals(null)) {
return "null";
}
if (value instanceof JSONStringer) {
Object o;
try {
o = ((JSONStringer) value).toString();
} catch (Exception e) {
throw new JSONException(e.getMessage());
}
if (o instanceof String) {
return (String) o;
}
throw new JSONException("Bad value from toJSONString: " + o);
}
if (value instanceof Number) {
return numberToString((Number) value);
}
if (value instanceof Boolean || value instanceof JSONObject || value instanceof JSONArray) {
return value.toString();
}
if (value instanceof Map) {
return new JSONObject((Map) value).toString();
}
if (value instanceof Collection) {
return new JSONArray((Collection) value).toString();
}
return quote(value.toString());
}
}
在最新的Android源码中, JsonObject中数据存储已经由HashMap更换为了LinkedHashMap,实现有序输出
参考:
1.http://blog.csdn.net/ben0612/article/details/44591161
相关文章
- 暂无相关文章
用户点评