【android基础】固定JSONObject.toString()键值对顺序
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了【android基础】固定JSONObject.toString()键值对顺序,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5834字,纯文字阅读大概需要9分钟。
内容图文
org.json.JSONObject相信很多人都用过,例如:服务端返回给客户端的数据格式是JSONObject的,那我们通过对它进行解析,把它显示在界面上。有时候希望服务器跟客户端通信的JSONObjectt的键值对顺序是固定的。
例如:
客户端提交一个JSONObject格式的数据,里面有三个键值对,分别是"a":"a" "b":"b" "c":"c"
服务端原封不动返回给客户端,这个客户端希望接到的是这样的
{"a":"a","b":"b","c":"c"}
但JSONObject的键值对顺序几乎不能确定的,无规律可循,验证如下:
1. <pre name="code" class="html"> JSONObject object=new JSONObject(); try { object.putOpt("b", "b"); object.putOpt("a", "a"); object.putOpt("c", "c"); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); }
object.toString(),得到的是
{"b":"b","c":"c","a":"a"}与put进去时候的顺序不一致。
2.
JSONObject object=new JSONObject(); try { object.putOpt("1", "1"); object.putOpt("2", "2"); object.putOpt("3", "3"); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); }object.toString(),得到的是
{"3":"3","2":"2","1":"1"}与put进去时候的顺序不一致 3.
JSONObject object=new JSONObject(); try { object.putOpt("我", "我"); object.putOpt("你", "你"); object.putOpt("他", "他"); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); }object.toString(),得到的是
{"你":"你","他":"他","我":"我"}
与put进去时候的顺序不一致。
以上三个例子,无论键和值是数字、字母还是中文,JSONObject put进去的顺序喝toString得到的顺序,是不一致的。
如果还有疑问,我们看看JSONObject的源码吧。
先看构造方法:
public JSONObject() { nameValuePairs = new HashMap<String, Object>(); }再看putOpt 以及put方法:
public JSONObject putOpt(String name, Object value) throws JSONException { if (name == null || value == null) { return this; } return put(name, value); } 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是散列的,是链式存储结构。
HashMap的存储过程,根据该元素自身提供的hashcode计算出散列值(在这一点上,就可以知道,元素放进去的位置是无法确定的,只有在获取hashcode后才知道),该值就是数组的下标,然后将该元素放入数组位置的链表中。
那么如何固定它的顺序呢,put进去是我们想要的呢?有两个方法:自定义JSONObject(不用HashMap改用LinkHashMap实现)或使用com.alibaba.fastjson.annotation.JSONType标注
1.自定义JSONObject(不用HashMap改用LinkHashMap实现),LinkedHashMap是有序的,代替无序的HashMap,把父类用到HashMap的地方都改成LinkedHashMap即可,主要是put跟toString的几个方法。
public class MyJSONObject extends JSONObject { private LinkedHashMap<Object, Object> mHashMap; public ChatMsgJSONObject() { mHashMap = new LinkedHashMap<Object, Object>(); } @Override public JSONObject put(String name, boolean value) throws JSONException { // TODO Auto-generated method stub return put(name, value); } @Override public JSONObject put(String name, double value) throws JSONException { // TODO Auto-generated method stub return put(name, value); } @Override public JSONObject put(String name, int value) throws JSONException { // TODO Auto-generated method stub return put(name, value); } @Override public JSONObject put(String name, long value) throws JSONException { // TODO Auto-generated method stub return put(name, value); } public JSONObject put(String key, Object value) throws JSONException { if (key == null) { throw new JSONException("Null key."); } if (value != null) { testValidity(value); mHashMap.put(key, value); } else { remove(key); } return this; } public Object remove(String key) { return mHashMap.remove(key); } static void testValidity(Object o) throws JSONException { if (o != null) { if (o instanceof Double) { if (((Double) o).isInfinite() || ((Double) o).isNaN()) { throw new JSONException("JSON does not allow non-finite numbers."); } } else if (o instanceof Float) { if (((Float) o).isInfinite() || ((Float) o).isNaN()) { throw new JSONException("JSON does not allow non-finite numbers."); } } } } public String toString() { try { Iterator<Object> keys = mHashMap.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(mHashMap.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()); } }2.使用fastjson.jar中的com.alibaba.fastjson.annotation.JSONType,用@JSONType来标注实体类
import com.alibaba.fastjson.annotation.JSONType; @JSONType(orders = { "type", "content", "locationUrl"}) public class MessageDto { private Sting type; private String content; private String locationUrl; public MessageDto() { } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getLocationUrl() { return locationUrl; } }使用如下:
MessageDto msg = new MessageDto(); msg.setContent("1"); msg.setLocationUrl("2"); msg.setType(3);那么com.alibaba.fastjson.JSON.toJSONString(msg),得到的就是
{"type":"3","content":"1","locationUrl":"2"},这跟标注的
(orders = { "type", "content", "locationUrl"})一致。
以上仅从技术角度来讨论。可能有的人会说,肯定不会有这样的需求,但我确实遇到过这样的需求。多谢。
原文:http://blog.csdn.net/ben0612/article/details/44591161
内容总结
以上是互联网集市为您收集整理的【android基础】固定JSONObject.toString()键值对顺序全部内容,希望文章能够帮你解决【android基础】固定JSONObject.toString()键值对顺序所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。