Gson教程三(译):Arrays和Lists的映射
来源:互联网 发布:淘宝卖家地址是真的吗 编辑:程序博客网 时间:2024/06/05 05:16
该文章翻译自Gson Tutorial Series系列教程。该篇主要阐述了如何使用Gson映射Arrays和List集合对象。
Arrays和Lists之间的不同
在进入正题之前,我们想阐述一下Arrays和Lists这两种Java数据结构。他们的Java实现是不同的并且各有各的优势。在你的用例中采取哪种方式取决于软件需求以及你个人的喜好。有趣的是,什么是选择list还是array结构映射到JSON是无关紧要的。
在JSON的数据格式中,没有lists和arrays。是的,Java的实现造成了二者之间巨大的区别,但在就高层次来说,他们都是代表相同的列表结构。在接下来的博客中,我们将他们成为对象列表,但是在Java中他们又是不同的。如果你对此感到迷惑,不用担心,一些例子将会使你更加清晰。
Arrays或者Lists数据的序列化
还记得前一篇博客中关于嵌套对象的restaurant模型吗?现在是时候为它增加一个菜单了。我们想要知道美味食物的价格。一个饭店的菜单可以看成是菜单项的列表结构。每一项都是可供顾客点单的。在我们的简易饭店中,每一项都包括描述和价格。
提示:我们没有考虑菜品分类,组合套餐以及配菜,这使我们的例子足够简单。这很明显不是一个完美的模型,因此不要在你的商业饭店App中使用它……
如果我们考虑怎样具体实现其Java模型,我们将得到接近如下的代码:
public class RestaurantWithMenu { String name; List<RestaurantMenuItem> menu; //RestaurantMenuItem[] menu; // alternative, either one is fine}public class RestaurantMenuItem { String description; float price;}
Java处理嵌套对象的方式和JSON是不同的。Java可以将之分离到不同的类中,并由List或者Array的来持有其引用。JSON需要保持一个本地的、嵌套的列表。这意味着在高层次,我们希望JSON像下面这样:
{ "name": "Future Studio Steak House", "menu": [ ... ]}
就像嵌套对象一样,menu并不拥有一个直接的值。相反,JSON为其值定义了一个由[]包裹着的对象列表。如上面提到的,这是array还是list是没有区别的。在JSON的数据结构中它看起来是相同的。
menu由很多对象组成。在我们的例子中,它们是饭店菜单项。让我们运行Gson查看一个完整的JSON会是什么样子。
我们希望你现在已经知道常规步骤了。得到你的Java对象,初始化Gson然后让Gson创建相应的JSON:
List<RestaurantMenuItem> menu = new ArrayList<>(); menu.add(new RestaurantMenuItem("Spaghetti", 7.99f)); menu.add(new RestaurantMenuItem("Steak", 12.99f)); menu.add(new RestaurantMenuItem("Salad", 5.99f));RestaurantWithMenu restaurant = new RestaurantWithMenu("Future Studio Steak House", menu);Gson gson = new Gson(); String restaurantJson = gson.toJson(restaurant);
restaurantJson包含如下内容:
{ "menu": [ { "description": "Spaghetti", "price": 7.99 }, { "description": "Steak", "price": 12.99 }, { "description": "Salad", "price": 5.99 } ], "name": "Future Studio Steak House"}
就跟通常一样,排序有点神奇,列表排在前面是因为按字母来说menu在name的前面。除了排序意外,其他一切都是我们希望的。列表(由[]包裹)包含多个对象(每一个对象由{}包裹)。
然而,我们并不总是发送一个嵌套了列表数据的单独对象,就像上面做的那样。有时候我们也希望发送一个列表。当然,Gson同样支持JSON列表的序列化。例如,如果我们希望序列化如下菜单项列表:
List<RestaurantMenuItem> menu = new ArrayList<>(); menu.add(new RestaurantMenuItem("Spaghetti", 7.99f)); menu.add(new RestaurantMenuItem("Steak", 12.99f)); menu.add(new RestaurantMenuItem("Salad", 5.99f));Gson gson = new Gson(); String menuJson = gson.toJson(menu);
将会得到如下结果:
[ { "description": "Spaghetti", "price": 7.99 }, { "description": "Steak", "price": 12.99 }, { "description": "Salad", "price": 5.99 }]
让我们指出重要的不同之处:该JSON的首个字符为[,这就提示了接下来是对象列表!到目前为止,我们只看到由{开始的对象。你应该马上记住它们之间的差异。你将总是需要它并在下一章节马上回用到,如果你继续阅读的话。
Arrays或者Lists的序列化和反序列化
在第二部分我们学习反序列化。换句话说,我们如何使用Gson映射JSON结构中的列表到Java对象。在之前的例子中,我们看到了JSON数据中作为根列表和嵌套在对象中的列表的重要不同。
列表作为根对象
让我们做一个练习。考虑这样一种情况,在未来的环境中我们将会开启自己的API,并会提供一个端口GET /founders。该端口将返回三个对象的数组,每个对象包含一个name域和一个flowerCount域。该数组代表我们桌子上的植物。因此如下JSON列表:
[ { "name": "Christian", "flowerCount": 1 }, { "name": "Marcus", "flowerCount": 3 }, { "name": "Norman", "flowerCount": 2 }]
是的,你是对的。这个想象的端口直接返回了一个列表。JSON以[]开始和结束。没错,Marcus也喜欢在绿植环绕的办公桌上工作。
因此,我们如何使用Gson将此映射到Java对象呢?第一步是创建模型:
public class Founder { String name; int flowerCount;}
第二部取决于你。你是希望使用Lists还是Arrays作为你的类型呢?
Arrays
如果你想要使用Arrays,那太简单了。跟之前一样直接调用fromJson()方法并且传递数组模型的class,就像:gson.fromJson(founderGson, Founder[].class);
String founderJson = "[{'name': 'Christian','flowerCount': 1}, {'name': 'Marcus', 'flowerCount': 3}, {'name': 'Norman', 'flowerCount': 2}]";Gson gson = new Gson(); Founder[] founderArray = gson.fromJson(founderJson, Founder[].class);
这将会产生一个founder的Java数组对象,它们的属性都映射正确:
Lists
鉴于Lists可以扩展容量,因此现在的开发者更喜欢使用Java Lists。不幸的是,你不能直接传递List给Gson。为了使Gson知道List的准确结构,你需要得到它的Type。幸运的是,Gson有一个TypeToken类帮助你正确找到任何类的Type。我们的Founder类在一个ArrayList中,让我们看一下:
Type founderListType = new TypeToken<ArrayList<Founder>>(){}.getType();
你可以使用该语句的结果作为type供Gson调用:
String founderJson = "[{'name': 'Christian','flowerCount': 1}, {'name': 'Marcus', 'flowerCount': 3}, {'name': 'Norman', 'flowerCount': 2}]";Gson gson = new Gson();Type founderListType = new TypeToken<ArrayList<Founder>>(){}.getType();List<Founder> founderList = gson.fromJson(founderJson, founderListType);
结果跟使用Array得到的结果差不多:
最后,映射你的数据到Array还是List取决于你的个人偏好和用例情况。让我们探讨另一个主题:怎样反序列化一个嵌套在一个对象中的列表:
列表作为一个对象的一部分
我们已经扩展了我们想象的未来环境中的API,端口为GET /info。它返回了比founder更多的信息:
{ "name": "Future Studio Dev Team", "website": "https://futurestud.io", "founders": [ { "name": "Christian", "flowerCount": 1 }, { "name": "Marcus", "flowerCount": 3 }, { "name": "Norman", "flowerCount": 2 } ]}
我们希望你已经熟悉流程了。首先我们需要写一个与JSON响应匹配的模型。我们可以复用之前的Founder类:
public class GeneralInfo { String name; String website; List<Founder> founders;}
处理嵌套在一个对象中的列表是简单的,因为Gson不用使用TypeToken就可以简单地处理了。我们可以直接传入class:
String generalInfoJson = "{'name': 'Future Studio Dev Team', 'website': 'https://futurestud.io', 'founders': [{'name': 'Christian', 'flowerCount': 1 }, {'name': 'Marcus','flowerCount': 3 }, {'name': 'Norman','flowerCount': 2 }]}";Gson gson = new Gson();GeneralInfo generalInfoObject = gson.fromJson(generalInfoJson, GeneralInfo.class);
产生的结果是完美的:
当然,你也可以使用Founder[]数组代替List。Gson同样可以处理。
注意:你注意到没有,GeneralInfo和Founder模型拥有相同的name属性,但是Gson却没有出现问题?在序列化和反序列化过程中不会出现任何问题。这真是太神奇了。
嵌套在列表里面的列表
如果你正好奇,在处理嵌套在列表里面的列表时会不会有问题。例如,下面的模型将不会有问题:
public class GeneralInfo { String name; String website; List<FounderWithPets> founders;}
FounderWithPets类是由宠物列表扩展而来的:
public class FounderWithPets { String name; int flowerCount; List<Pet> pets;}
Pet类又拥有玩具的列表
public class Pet { String name; List<Toy> toys;}
Toy类又包含……好了,循环停止吧。我们希望这个推论可以带给你这样一个观点:你可以在列表中逐层的包含列表而不会有任何问题。Gson就像个冠军一样良好的处理序列化和反序列化。
不过,Gson只能处理包含一致性的对象的列表。如果对象是完全不同的,Gson就不能映射了。尽管可以由多种类型组成列表。
- Gson教程三(译):Arrays和Lists的映射
- Gson - Arrays 和 Lists 对象映射
- Gson教程四(译):Maps的映射
- Gson教程五(译):Sets的映射
- Gson教程六(译):空值的映射
- Gson教程七(译):@SerializedName和@Expose
- Gson教程八(译):GsonBuilder基础和命名策略
- Gson教程一(译):Java-JSON的序列化和反序列化
- Gson教程二(译):嵌套对象的序列化和反序列化
- Gson教程十二(译):Float和Double类型的特殊值
- Gson教程十一(译):轻松使用仁慈的Gson(容错机制)
- Google Gson:POJO 和 JSON 的字段映射规则
- Shell教程(三):数组/Arrays、基本运算符
- Gson教程十(译):Exclusion Strategies
- asp.net2.0中的collections 和lists(Arrays)
- springmvc(三)注解的处理器映射器和适配器
- SpringMVC入门及系列教程(三)-请求的映射(详细)
- 你真的会用Gson吗?Gson使用指南(三)
- OkHttp的拦截器机制分析
- (一).初学STC89C52单片机
- 一文了解机器学习开发工具
- DrawerLayout和NavigationView轻松实现抽屉侧滑
- ion-nav-bar
- Gson教程三(译):Arrays和Lists的映射
- 键索引计数法
- 关于地图的一些知识
- 利用shell脚本从SFTP服务下载上传文件
- help & manual 写产品手册
- CentOS7上解决tomcat不能被外部浏览访问
- JSP JSTL界面是否包含的判断 fn:contains()函数
- 高精度数取余(C\C++)
- java高并发程序设计总结五:jdk并发包其他同步控制工具类:ReadWriteLock/CountDownLatch/CyclicBarrier/LockSupport