在Gson中传递uri对象
来源:互联网 发布:用相对坐标编程图例 编辑:程序博客网 时间:2024/05/14 10:19
GSON
gson是安卓开发中一个流行的Json格式转换包。只要简单的两行代码就可以实现自定义对象和JSON格式的互转。从而极大地简化数据传递前的序列化操作。
官方github在这里https://github.com/google/gson
// 将person类对象转JSON格式Gson gson = new Gson();String personInStringToAdd = gson.toJson(personToAdd);
// 将JSON格式转回person类Gson gson = new Gson();final MyPerson selectedPerson = gson.fromJson(personInString, MyPerson.class);
当对象中存在uri成员时
如果我们有以下一个类:
public class person { private String name; private Uri imagePath; public setImageUri(Uri path) {imagePath = path;} public Uri getImageUri(){return imagePath;}}
我们对这个类进行序列化操作,发现是可以的。然后解序列化的时候程序崩溃,我们跟踪发现是这一行出现了问题:
final MyPerson selectedPerson = gson.fromJson(personInString, MyPerson.class);
原因
百思不得解,通过排除法发现是Myperson类中多了Uri类型成员的问题。
后来查官方文档 https://github.com/google/gson/blob/master/UserGuide.md#TOC-Gson-With-Gradle,发现:
However, Gson can not automatically deserialize the pure inner classes since their no-args constructor also need a reference to the containing Object which is not available at the time of deserialization.
大概就是说,当类中包含有内部类的时候,不能直接deserialize,因为这时指向内部类的无参构造函数还不可用。
可能我们这里并不能算内部类,但原因应该是差不多的。
解决
官方文档给了两个解决办法:
方法一
将内部类设为static,即静态的。在这个例子中,就是变成这样,但这显然不符合我们的需求,我们要每一个person对象都有一个头像,而设为static就所有对象共享一个头像了。
public class person { private String name; // 多了个"static" static private Uri imagePath; public setImageUri(Uri path) {imagePath = path;} public getImageUri(){return imagePath;}}
方法二
自己实现custom instance creator 接口。
在StackOverflow找到一个比官方说的更清楚的答案https://stackoverflow.com/questions/22533432/create-object-from-gson-string-doesnt-work
翻译过来大概就是这样:
首先实现两个类:
// 反序列化器public class UriSerializer implements JsonSerializer<Uri> { public JsonElement serialize(Uri src, Type typeOfSrc, JsonSerializationContext context) { return new JsonPrimitive(src.toString()); }}// 序列化器public class UriDeserializer implements JsonDeserializer<Uri> { @Override public Uri deserialize(final JsonElement src, final Type srcType, final JsonDeserializationContext context) throws JsonParseException { return Uri.parse(src.getAsString()); }}
然后,使用Gson的时候,就要挂在对于Uri的序列化器和反序列化器了,像这样:
// 序列化Gson gson = new GsonBuilder() .registerTypeAdapter(Uri.class, newUriSerializer()) .create();String personInString = gson.toJson(myPerson);
// 反序列化Gson gson = new GsonBuilder() .registerTypeAdapter(Uri.class, new UriDeserializer()) .create();person myPerson = gson.fromJson(personInString, person.class);
方法三
方法三是宿友灵光一闪想出来的。
既然反序列化失败的原因是,类中存在内部类,那么,如果我们以String方法来保存我们的类呢?String是原生类型,Gson是一定支持的。
于是有了这个曲线救国的机智方法。
public class person { private String name; private String imagePath; public setImageUri(Uri path) {imagePath = path.toString();} public Uri getImageUri(){return Uri.parse(imagePath);}}
就这么机智!!
我们的接口返回和接受的仍然是Uri,但是在内存中存的时候确实以String来存。这样,就可以直接用Gson直接对类进行序列化,而不需要写序列化器和反序列化器!节省了多少代码!
反思
我们是使用第三方包的时候遇到类似问题,首先应该可以考虑的是,能不能通过转换成基础类型来解决,因为基础类型是一定支持了(如果不支持,这个第三方包意义不大吧?)。
这样的话,只需要在类中更改一下接口实现就可以了。修改成本是极低的。
如果不能,再考虑其他官方方法。
- 在Gson中传递uri对象
- Gson的使用-----可用在界面之间传递对象等
- Gson传递和解析对象/集合
- 在ATL DLL中传递C++对象
- 在ATL DLL中传递C++对象
- strom实战--在Bolt中传递对象
- 在dobbu中对象传递属性不存在。
- 在函数中传递一个对象
- Gson处理前端传递过来的Json对象数组
- android初学------json字符串数组转对象 保存在list集合中 Gson
- 在Android中通过Intent使用Bundle传递对象
- 在Android中通过Intent使用Bundle传递对象
- 在Android中通过Intent使用Bundle传递对象
- 在Android中通过Intent使用Bundle传递对象
- 在Android中通过Intent使用Bundle传递对象
- 在MFC中实现对象之间数据的传递。
- 为什么在Pool中传递Queue对象无法运行
- 在Android中通过Intent使用Bundle传递对象
- 关于$_SERVER中的PHP_SELF、REQUEST_URI以及SCRIPT_NAME的区别
- apache和tomcat有什么不同,为什么要整合apache 和tomcat?
- 最大公约数-辗转相除法
- android后台通过View生成分享图片
- irun增量编译
- 在Gson中传递uri对象
- mysql 追加update_time、create_time、id三字段
- 数据库事务特性、并发、隔离级别、锁种类、锁粒度
- Django使用自定义验证
- C语言回调函数
- 自顶向下,逐步求精
- 机器学习的数学基础(1)——常见的函数与分布
- 解决Eclipse打开后无项目问题
- L