android 自带的json解析很繁琐,看外国人大多都是使用gson ..所以咯
选择gson原因:<摘抄的>
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。易于人阅读和编写,同时也易于机器解析和生成。它基于JavaScript(Standard ECMA-262 3rd Edition - December 1999)的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。
Android的SDK中包含四个与JSON相关的类和一个Exceptions:JSONArray、JSONObject、JSONStringer、JSONTokener、JSONException。通过这5个类我们就可以自行对Json进行解析(使用很简单,可以网上搜索使用方法或者参照Android SDK),另外Google在Android的SDK中放入了JsonReader和JsonWriter来方便我们读写Json。但是通过他们读写Json还都要停留到手工操作上,无法直接实现Json字符串到对象、对象到Json字符串的转换,例如解析Json需要通过Key值一个一个的取Value,工作量大不说,还增加了出错的几率。有没有办法可以:直接实现Json字符串到对象、对象到Json字符串的转换?
在Java EE中使用最广泛的是Jackson Json(据说是集成到Spring中的,我不太清楚),使用非常方便而且效率极高;另外还有两个比较有名气的是Gson和JSON-lib,某些大侠已经对它们做了对比实验,结论如下执行效率:Jackson>Gson>JSON-lib,但是鉴于我们要将解析库集成到Android应用当中,我们还要考虑一下嵌入的库的体积,分别取他们的最新版本:
jackson-all-1.9.0.jar 1.1MB
gson-1.7.1.jar 174KB
json-lib-2.4-jdk15.jar 159KB (2010年12月开始已经停止更新了)
通过这个比较我们几乎可以直接排除掉jackson(为了解析JSON方便而让软件增加1.1MB?),而json lib执行效率低下且已经停止了更新,我们也不希望选用。另外jackson生于Jave EE,完全符合java bean惯例是对getter进行序列化,而gson是对成员变量field进行序列化,Android恰恰是推荐开发者直接使用成员变量访问而不是用setter、getter。最终我们选择了Google出品的Gson,至于Gson如何使用,欢迎关注下一篇文章。
网络实例:
通过把JSON数据映射成一个对象,使用Gson对象的fromJson()方法获取一个对象数组进行操作:
创建JSON数据对应的一个POJO对象User.java:
public class User {
private String username ;
private int userId ;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
}
使用Gson对象获取User对象数据进行相应的操作:
Type listType = new TypeToken<LinkedList<User>>(){}.getType();
Gson gson = new Gson();
LinkedList<User> users = gson.fromJson(jsonData, listType);
for (Iterator iterator = users.iterator(); iterator.hasNext();) {
User user = (User) iterator.next();
System.out.println(user.getUsername());
System.out.println(user.getUserId());
}
如果要处理的JSON字符串只包含一个JSON对象,则可以直接使用fromJson获取一个User对象:
String jsonData = "{\"username\":\"arthinking\",\"userId\":001}";
Gson gson = new Gson();
User user = gson.fromJson(jsonData, User.class);
System.out.println(user.getUsername());
System.out.println(user.getUserId());
Android 用Gson来序列化和返序列化对象
Gson官网
http://code.google.com/p/google-gson/
JavaDoc
http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/index.html
-----------------------------------------------------------------
下载内容:
google-gson-2.1-release.zip
-----------------------------------------------------------------
扫盲:
Json是一种类似于XML的通用数据交换格式,具有比XML更高的传输效率.
从结构上看,所有的数据(data)最终都可以分解成三种类型:
第一种类型是标量(scalar),也就是一个单独的字符串(string)或数字(numbers),比如"北京"这个单独的词。
第二种类型是序列(sequence),也就是若干个相关的数据按照一定顺序并列在一起,又叫做数组(array)或列表(List),比如"北京,上海"。
第三种类型是映射(mapping),也就是一个名/值对(Name/value),即数据有一个名称,还有一个与之相对应的值,这又称作散列(hash)或字典(dictionary),比如"首都:北京"。
Json的规格非常简单,只用一个页面几百个字就能说清楚,而且Douglas Crockford声称这个规格永远不必升级,因为该规定的都规定了。
1) 并列的数据之间用逗号(",")分隔。
2) 映射用冒号(":")表示。
3) 并列数据的集合(数组)用方括号("[]")表示。
4) 映射的集合(对象)用大括号("{}")表示。
-----------------------------------------------------------------
最快速入门贴:
1. 对象的序列化和反序列化
Type listType = new TypeToken<List<String>>() {}.getType(); L
ist<String> target = new LinkedList<String>();
target.add("blah");
Gson gson = new Gson();
String json = gson.toJson(target, listType);
List<String> target2 = gson.fromJson(json, listType);
OK,最简方案打完收工.2.使用GsonBuilder.GsonBuilder用来生成Gson对象. 规定Gson的序列化和返序列化时的格式等内容.如:
Gson gson = new GsonBuilder() .registerTypeAdapter(Id.class, new IdTypeAdapter())
.enableComplexMapKeySerialization()
.serializeNulls()
.setDateFormat(DateFormat.LONG)
.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
.setPrettyPrinting()
.setVersion(1.0)
.create();
3. 使用注解,定制序列化字段.默认情况下注解是不起作用的,除非你用GsonBuilder创建Gson的时候调用了GsonBuilder.excludeFieldsWithoutExposeAnnotation()方法
来个例子:
public class User {
@Expose private String firstName;
@Expose(serialize = false) private String lastName;
@Expose (serialize = false, deserialize = false)
private String emailAddress; private String password;
}
如果你创建Gson对象的时候使用的是new Gson(),toJson()和fromJson()方法将会对全部的字段生效.但是如果你使用的是GsonBuilder并且调用了excludeFieldsWithoutExposeAnnotation()方法.那么:toJson()和fromJson()将不会包括password.因为password没有包含@Expose注解.序列化的时候将不包括 lastName和emailAddress,因为注解中标明不进行序列化.同样的道理,反序列化时将不包括emailAddress.注:如果仅仅是想把某些特定的字段包含在外和话,可以使用
transient 关键字声明字段.4. 使用注解对序列化名称进行声明这个简单,上例子都能懂,不解释:
public class SomeClassWithFields {
@SerializedName("name") private final String someField;
private final String someOtherField;
public SomeClassWithFields(String a, String b) {
this.someField = a; this.someOtherField = b;
}
}
===== OUTPUT =====
{"name":"a","someOtherField":"b"}
5. 例用注解,根据版本进行序列化有的字段不是一开始就有的,会随着版本的升级添加进来,那么在进行序列化和返序列化的时候就会根据版本号来选择是否要序列化.
@Since(版本号)能完美地实现这个功能.当然,
GsonBuilder.setVersion(double)方法需要调用.例程如下:
public class User {
private String firstName;
private String lastName;
@Since(1.0) private String emailAddress;
@Since(1.0) private String password;
@Since(1.1) private Address address;
}
还的字段可能,随着版本的升级而删除,那么@Until(版本号)也能实现这个功能,
GsonBuilder.setVersion(double)方法需要调用.
public class User {
private String firstName;
private String lastName;
@Until(1.1) private String emailAddress;
@Until(1.1) private String password;
}
Gson解析json数据很是强大,但有的时候如果使用不当,也很麻烦。
1 “循环序列化” 异常
解决方法为在可能造成的循环序列化的字段加上 transient。
transient private Menu parent;//父节点
2 排序特定字段
比如 :User的json数据为{id:”1” , name:”syxchina”, password:”syx”},我们解析的时候是不想把password解析,我们想得到格式为:{id:”1” , name:”syxchina”}。
第一种方法是使用Gson自带的注解,但任何时候取数据都没的那个字段。
第二种方法使用GsonBuilder,设置ExclusionStrategy参数。
//原串:{id:"1" , name:"syx", password:"syx"}
//效果:{id:"1" , name:"syx"}
private static Gson gsonMenuComboTree = new GsonBuilder()//
.setExclusionStrategies(new MenuTreeExclusionStrategy())//
.create();
private static class MenuTreeExclusionStrategy implements ExclusionStrategy{
public boolean shouldSkipField(FieldAttributes f) {
if("password".equals(f.getName())) return true;
return false;
}
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
}
3 修改字段json显示
//JSON: {id:"1" , name:"syx", password:"syx"}
//OUT : {id:"1" , name:"syx", modifyField:"syx"}
private static Gson gsonMenuComboTree = new GsonBuilder()//
.setFieldNamingStrategy(new MenuTreeFieldNamingStrategy())//
.create();
private static class MenuTreeFieldNamingStrategy implements FieldNamingStrategy {
public String translateName(Field f) {
if ("password".equals(f.getName())) {
return "modifyField";
}
return f.getName();
}
}
作者:syxChina
出处:http://syxchina.cnblogs.com、 http://hi.bai
du.com/syxcs123
本文版权归作者、博客园和百度空间共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则作者会诅咒你的。
==========================================
在定义泛型时候 如:
class User{
@Expose
int _id;
@Expose
@SerializedName("name")
String Name;
}
其中 @Expose 是用GsonBuilder 创建 Gson ,然后GsonBuilder调用了excludeFieldsWithoutExposeAnnotation(),规定了只有包含@Expose的才会被解析,而@SerializedName("name") 就是把json数据中的“name”关键字的值,解析到自己定义的Name关键字下