我为什么强推-Gson序列化神器 | 再也不用担心复杂数据结构字段值了

80 阅读5分钟

前言

大家好,欢迎来到软件工程师令狐本期文章。最近做一个中间件项目的时候,涉及到从第三方系统收数据过来到我们自己的系统,我拿对象去接收就一定要涉及到对象的序列化与反序列化。我本来用的是阿里巴巴的FastJson,但我发现这个工具其实很不稳定,性能不太好。我调研发现Gson是目前性能最稳定的项目。

在我做项目重构升级的时候,我决定序列化工具改成Gson!这篇文章就是介绍Gson相关的知识点与应用。

[TOC]

关于对象的序列化与反序列化

这两个概念不难理解。

序列化

JavaBean转换为json字符串。【比较粗暴的理解】

反序列化

Json字符串转换为JavaBean【比较粗暴的理解】

快速入门 | Demo

序列化有三种场景,分别是:

  • JavaBean转换为Json字符串
  • List集合转Json字符串
  • Map集合转Json字符串

依赖引入

这个Gson其实是Google公司推出的,个人比较推荐。

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.6</version>
</dependency>

定义JavaBean

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
    private String name;
    private int age;
    private String sex;
    private List<String> hobbies;
}

Person作为我们要用的统一实体类,后面会一直使用。

JavaBean转换为Json字符串

Gson gson = new Gson(); 生成一个gson工具,要用到的工具函数就是 toJson()

   /** 将JavaBean转换为json,或将json字符串转换为JavaBean。 */
    @Test
    public void testBeantoJson(){
        Person person = new Person("linghu",26,"男",Arrays.asList("打球","看电影"));
        Gson gson = new Gson();
        String json = gson.toJson(person);
        System.out.println("json字符串为:"+json);
    }
List集合转Json字符串
@Test
    public void testListToJson(){
        List<Person> list = new ArrayList<>();
        list.add(new Person("linghu",26,"男",Arrays.asList("打球","看电影")));
        list.add(new Person("zhangsan",16,"男",Arrays.asList("吃火锅","看电影")));
        Gson gson = new Gson();
        String jsonList = gson.toJson(list);
        System.out.println("jsonList为:"+jsonList);
//        List fromJson = gson.fromJson(jsonList, List.class);//这种方法不安全,不推荐
        List<Person> fromJson = gson.fromJson(jsonList, new TypeToken<List<Person>>() {}.getType());
        System.out.println("---------------------");
        fromJson.stream().forEach(System.out::println);
    }
jsonList为:[{"name":"linghu","age":26,"sex":"男","hobbies":["打球","看电影"]},{"name":"zhangsan","age":16,"sex":"男","hobbies":["吃火锅","看电影"]}]
---------------------
Person(name=linghu, age=26, sex=男, hobbies=[打球, 看电影])
Person(name=zhangsan, age=16, sex=男, hobbies=[吃火锅, 看电影])
Map集合转Json字符串
 @Test
    public void testMapToJson(){
        Map<String, Person> hashMap = new HashMap<>();
        hashMap.put("p1", new Person("linghu",26,"男",Arrays.asList("打球","看电影")));
        hashMap.put("p2", new Person("zhangsan",16,"男",Arrays.asList("吃火锅","看电影")));
        Gson gson = new Gson();
        String json = gson.toJson(hashMap);
        System.out.println("json字符串:"+json);
        System.out.println("---------------------");
        Map<String, Person> jsonMap = gson.fromJson(json, new TypeToken<Map<String, Person>>() {}.getType());
        for (Map.Entry<String, Person> personEntry : jsonMap.entrySet()) {
            System.out.println("key:"+personEntry.getKey()+" value:"+personEntry.getValue());
        }

    }
json字符串:{"p1":{"name":"linghu","age":26,"sex":"男","hobbies":["打球","看电影"]},"p2":{"name":"zhangsan","age":16,"sex":"男","hobbies":["吃火锅","看电影"]}}
---------------------
key:p1 value:Person(name=linghu, age=26, sex=男, hobbies=[打球, 看电影])
key:p2 value:Person(name=zhangsan, age=16, sex=男, hobbies=[吃火锅, 看电影])
Json字符串转JavaBean

要用到的工具函数就是 fromJson()

@Test
    public void testBeantoJson(){
        Person person = new Person("linghu",26,"男",Arrays.asList("打球","看电影"));
        Gson gson = new Gson();
        System.out.println("---------------------");
        Person personObeject = gson.fromJson(json, Person.class);
        System.out.println("Person对象为:"+personObeject);
    }

Gson实战 | 牛刀小试

当我们真的拿到一组数据的时候,我们需要去不断拆解,需要不断序列化和反序列化。

我们一定要用的工具就是在线json转换工具:www.json.cn/

用在线工具的目的是看清楚数据结构,分析如何拿到我们想要的字段-对应的数据值。

案例:

        String message = "{\"orderId\":\"example\",\"appProductId\":\"example\",\"productId\":\"example\",\"productName\":\"example\",\"begintime\":\"example\",\"duration\":\"example\",\"endtime\":\"example\",\"products\":\"[{\\\"app_product_id\\\":\\\"example\\\",\\\"app_sku_id\\\":\\\"example\\\",\\\"product_id\\\":1000,\\\"sku_id\\\":\\\"example\\\",\\\"quantity\\\":1,\\\"amount\\\":\\\"example\\\",\\\"desc\\\":\\\"example\\\",\\\"product_type\\\":1,\\\"related_product\\\":\\\"example\\\",\\\"card_total_number\\\":1,\\\"card_consumption_number\\\":1,\\\"card_remain_number\\\":1,\\\"adv_service_techId\\\":\\\"example\\\",\\\"period_orderId\\\":\\\"example\\\",\\\"uni_order_id\\\":\\\"example\\\",\\\"product_name\\\":\\\"example\\\"}]\",\"userName\":\"example\",\"userGender\":\"example\",\"mobile\":\"example\",\"appPeriodId\":\"example\",\"userAge\":\"example\",\"identityNum\":\"example\",\"chargeMode\":\"example\",\"married\":\"example\",\"amount\":\"example\",\"orderShoppromoDetails\":\"[{\\\"promo_type\\\":1,\\\"promo_amount\\\":\\\"example\\\",\\\"desc\\\":\\\"example\\\"}]\",\"quantity\":\"example\",\"comment\":\"example\",\"bizType\":\"example\",\"relatedServiceItem\":[{\"price\":\"example\",\"quantity\":1,\"sku_id\":\"example\",\"app_sku_id\":\"example\",\"app_product_id\":\"example\"}],\"userAddress\":\"{\\\"receiver_name\\\":\\\"example\\\",\\\"receiver_address\\\":\\\"example\\\",\\\"remark\\\":\\\"example\\\",\\\"latitude\\\":\\\"example\\\",\\\"use_receiver_virtual_number\\\":\\\"example\\\",\\\"longitude\\\":\\\"example\\\",\\\"receiver_mobile\\\":\\\"example\\\",\\\"receiver_phone\\\":\\\"example\\\"}\",\"type\":\"example\",\"deliveryAddress\":\"{}\",\"phone\":\"example\",\"useVirtualNumber\":\"example\",\"lockReceipt\":\"example\",\"platform\":\"example\",\"acceptType\":\"example\",\"techId\":\"example\"}";

上面的message是我们获取到的某个三方系统给我们的数据,我们接下来如何获取里面对应想要的值呢?

json转换

用在线工具www.json.cn/ 首先把上面的数据结构展示出来:

在这里插入图片描述

  • 一开始我们可以根据对应的字段新建对应的实体类
    • 在这里插入图片描述
  • 分析对应的字段是什么数据结构 ??map or List?List里装了很多个json?
  • 取出对应值填充到我们建好的实体类里作为新的对象
 @Test
    public void test(){
        String message = "{\"orderId\":\"example\",\"appProductId\":\"example\",\"productId\":\"example\",\"productName\":\"example\",\"begintime\":\"example\",\"duration\":\"example\",\"endtime\":\"example\",\"products\":\"[{\\\"app_product_id\\\":\\\"example\\\",\\\"app_sku_id\\\":\\\"example\\\",\\\"product_id\\\":1000,\\\"sku_id\\\":\\\"example\\\",\\\"quantity\\\":1,\\\"amount\\\":\\\"example\\\",\\\"desc\\\":\\\"example\\\",\\\"product_type\\\":1,\\\"related_product\\\":\\\"example\\\",\\\"card_total_number\\\":1,\\\"card_consumption_number\\\":1,\\\"card_remain_number\\\":1,\\\"adv_service_techId\\\":\\\"example\\\",\\\"period_orderId\\\":\\\"example\\\",\\\"uni_order_id\\\":\\\"example\\\",\\\"product_name\\\":\\\"example\\\"}]\",\"userName\":\"example\",\"userGender\":\"example\",\"mobile\":\"example\",\"appPeriodId\":\"example\",\"userAge\":\"example\",\"identityNum\":\"example\",\"chargeMode\":\"example\",\"married\":\"example\",\"amount\":\"example\",\"orderShoppromoDetails\":\"[{\\\"promo_type\\\":1,\\\"promo_amount\\\":\\\"example\\\",\\\"desc\\\":\\\"example\\\"}]\",\"quantity\":\"example\",\"comment\":\"example\",\"bizType\":\"example\",\"relatedServiceItem\":[{\"price\":\"example\",\"quantity\":1,\"sku_id\":\"example\",\"app_sku_id\":\"example\",\"app_product_id\":\"example\"}],\"userAddress\":\"{\\\"receiver_name\\\":\\\"example\\\",\\\"receiver_address\\\":\\\"example\\\",\\\"remark\\\":\\\"example\\\",\\\"latitude\\\":\\\"example\\\",\\\"use_receiver_virtual_number\\\":\\\"example\\\",\\\"longitude\\\":\\\"example\\\",\\\"receiver_mobile\\\":\\\"example\\\",\\\"receiver_phone\\\":\\\"example\\\"}\",\"type\":\"example\",\"deliveryAddress\":\"{}\",\"phone\":\"example\",\"useVirtualNumber\":\"example\",\"lockReceipt\":\"example\",\"platform\":\"example\",\"acceptType\":\"example\",\"techId\":\"example\"}";
        Gson gson = new Gson();
        Map<String, Object> o = gson.fromJson(message, new TypeToken<Map<String, Object>>() {}.getType());
        OrderMessage orderMessage = new OrderMessage();
        for (Map.Entry<String, Object> entry : o.entrySet()) {
            System.out.println("key:"+entry.getKey()+" value:"+entry.getValue());
            if (entry.getKey().equals("orderId")){
                orderMessage.setOrderId((String) entry.getValue());
            }
            if (entry.getKey().equals("products") && StringUtils.isNotBlank(entry.getKey())){
//                System.out.println("products:"+entry.getValue());
                List<Map<String, Object>> products = gson.fromJson(entry.getValue().toString(), new TypeToken<List<Map<String, Object>>>() {}.getType());
                for (Map<String, Object> maps :products) {
//                    System.out.println(maps);
                    Double quantity = (Double) maps.get("quantity");
//                    System.out.println("quantity:"+quantity);
                }

            }
            if (entry.getKey().equals("appProductId")){
                orderMessage.setAppProductId((String) entry.getValue());
            }
            if (entry.getKey().equals("orderShoppromoDetails")){
                OrderShoppromoDetails orderShoppromoDetails = new OrderShoppromoDetails();
                List<Map<String, Object>> o1 =gson.fromJson(entry.getValue().toString(),new TypeToken<List<Map<String, Object>>>() {}.getType());
                for (Map<String, Object> stringObjectMap :o1) {
                    log.info("map:{}",stringObjectMap);
                    if (stringObjectMap!=null){
                        orderShoppromoDetails.setPromo_type((Double) stringObjectMap.get("promo_type"));
                        orderShoppromoDetails.setDesc((String) stringObjectMap.get("desc"));
                        orderShoppromoDetails.setPromo_amount((String) stringObjectMap.get("promo_amount"));
                    }
                }
                orderMessage.setOrderShoppromoDetails(orderShoppromoDetails);
            }

            if (entry.getKey().equals("relatedServiceItem")){
                RelatedServiceItem relatedServiceItem = new RelatedServiceItem();
                List<Map<String, Object>> item = gson.fromJson(entry.getValue().toString(),new TypeToken<List<Map<String, Object>>>() {}.getType());
                for (Map<String,Object> stringObjectMap :item) {
                    if (stringObjectMap!=null){
                        relatedServiceItem.setPrice((String) stringObjectMap.get("price"));
                        relatedServiceItem.setQuantity((Double) stringObjectMap.get("quantity"));
                        relatedServiceItem.setSku_id((String) stringObjectMap.get("sku_id"));
                        relatedServiceItem.setApp_sku_id((String) stringObjectMap.get("app_sku_id"));
                        relatedServiceItem.setApp_product_id((String) stringObjectMap.get("app_product_id"));
                    }
                }
                orderMessage.setRelatedServiceItem(relatedServiceItem);
            }

            if (entry.getKey().equals("userAddress")){
                UserAddress userAddress = new UserAddress();
                Map<String, Object> mapLists = gson.fromJson(entry.getValue().toString(),new TypeToken<Map<String, Object>>() {}.getType());
                if (!mapLists.isEmpty()){
                    userAddress.setReceiver_name((String) mapLists.get("receiver_name"));
                    userAddress.setReceiver_address((String) mapLists.get("receiver_address"));
                    userAddress.setRemark((String) mapLists.get("remark"));
                    userAddress.setLatitude((String) mapLists.get("latitude"));
                    userAddress.setUse_receiver_virtual_number((String) mapLists.get("use_receiver_virtual_number"));
                    userAddress.setLongitude((String) mapLists.get("longitude"));
                    userAddress.setReceiver_mobile((String) mapLists.get("receiver_mobile"));
                    userAddress.setReceiver_phone((String) mapLists.get("receiver_phone"));
                }
                orderMessage.setUserAddress(userAddress);
            }
        }
        log.info("orderMessage:{}",orderMessage);
    }

gson.fromJson(entry.getValue().toString(),new TypeToken<List<Map<String, Object>>>() {}.getType());这种用法是我特别喜欢的一类用法。非常灵活。在Gson库中,gson.fromJson() 方法用于将JSON字符串反序列化为Java对象。new TypeToken<List<Map<String, Object>>>() {}.getType():这是一个类型令牌(Type Token),用于指定fromJson()方法应该期望的返回类型。在这个例子中,你期望的是一个List,其中包含了Map<String, Object>类型的元素。Gson使用这种类型令牌技术来在运行时捕获泛型类型信息,因为Java的泛型在编译时会被类型擦除。