我平时使用到的Json库主要是Gson,为了更 进一步了解我对Gson做了比较详细的学习
Gson的API设计
首先了解一下Gson的关于json的主要API,最顶层的类是JsonElement(表示这是一个Json对象),子类有如下几个
1、JsonArray 数组形式,可以理解为List类型的数据,如 [ {'a':'a'}, {'b','b'} ]等
2、JsonNull 指null类型
3、JsonObject:指的是标准的json对象{'a':'a' },并且提供了一系列方法,如添加属性 jsonObject.addProperty("b","b") , 还可以添加其他JsonElement,如jsonObject.add("a",jsonElement),这里jsonElement可以为任何JsonElement及其子类
4、JsonPrimitive:指原始类型
Gson反序列化时(如果有泛型)是如何获取泛型的具体类型的
我们知道java在运行的时候是用了泛型擦除的机制,在运行期,其实所有泛型都是Object类型的,我们如果设想自己想要实现反序列化(也就是将字符串转为对象)我们可能会这样
1、解析数据 如果为 [ { 'username' :' abc123' , 'password': '666'' } ] ,得到键值对如 :username = abc123等
2、拿到要转化对象的类型如果为 List<Person> aa = new ArrayList<Person>();, 我们可能想象有一个方法可以通过aa.getClass()然后通过class来获得Person类型,但是这里jdk里面是没有这样的方法的,那我们如何获得呢
Type type = new TypeToken<List<Person>>(){}.getType();
通过Type就能获得class了,其实这里是利用了jdk中class的一个方法getGenericSuperclass();可以通过class获得当前类的父类的泛型参数类型,了解了原理我们再看
Gson的实现,其实是创建了一个匿名内部类,这个类的父类是TypeToken,而参数类型就是我们想要转换的类型
Gson使用篇
Gson的使用很简单,将对象转化为json
Gson g = new Gson();
g.toJson(object);
自定义Gson
1 如果想要得到自定义的效果(如想要自定义日期格式)
可以这样常见gson
Gson g = new GsonBuilder().setDateFormat("yyyy-MM-dd hh-mm-ss ").create();
2 自定义某个字段的输出名称
如果有一个类
class Person{
private String id;
private String username;
private String desc;
}
在序列化的时候,我们想要将id变为 person_id,username变为 uname,我们可以设置fieldNamingStrategy(字段命名策略)
自定义命名策略需要实现FieldNamingStrategy接口,然后实现里面的translateName方法
class PersonFieldNamingStrategy{
public String translatename(Field f){
if(f.getName().equals("id"))return "person_id";
if(f.getName().equals("username")) return "uname";
}
}
gson在对字段进行序列化的时候都会调用translateName方法,我们就可以再这里进行字段名的修改,
其实修改字段序列化名称还有一种比较简单的方法,那就是给对象加上注解,如
@SerializedName("person_id")
private String id;
这样在序列化时就会生成 {'person_id' : '001'}
3 如果序列化时想要排除某些字段
拿上面的Person举例,如果我们序列化时想要排除id字段
自定义排除策略,这需要实现ExcludeStrategy
class PersonExcludeStrategy implements ExcludeStrategy{
//如果不想序列化某个类就在这里返回true
public boolean shouldSkipClass(Class<?> arg0) {
return false;
}
//如果不想序列化某个字段
public boolean shouldSkipField(FieldAttributes f) {
if(f.getName().equals("id"))return true;
return false;
}
}
这样序列化就能排除id字段 , 如果字段为 tranisent,则不会序列化
4 自定义序列化器,和反序列化器
如果想要更灵活的方式来控制序列化和反序列化,我们就要自定义自己的Serializer和Deserializer了
自定义Serializer(序列化器)
class PersonSerializer implements JsonSerializer<Person>{
public JsonElement serialize(Person p, Type type,JsonSerializationContext context) {
//在这里返回任何类型的JsonElement,gson会直接序列化这里返回的jsonElement
}
}
如果要使用这个Serializer,我们需要注册
Gson g = new GsonBuilder().registerTypeAdapter(Person.class,PersonSerializer)
反序列化器也是差不多,需要实现JsonDeserializer
class PersonDeserializer implements JsonDeserializer<Person>{
public Person deserialize(JsonElement elt, Type type,JsonDeserializationContext context) throws JsonParseException {
if(elt.isJsonObject()){
JsonObject j = (JsonObject) elt;
Person p = (Person)type.getClass().newInstance();
p.setUsername( j.getProperty("username") .getAsString() ) ;
}
}
}
注册反序列化器
Gson g = new GsonBuilder().registerTypeAdapter(Person.class, PersonDeserializer);
这里说了更多关gson使用的 介绍 http://blog.csdn.net/zxhoo/article/details/21471005
http://blog.csdn.net/canchew/article/details/7545363