zoukankan      html  css  js  c++  java
  • 全栈之路-小程序API-Json数据类型的序列化与反序列化

      MySQL中有一种新的数据结构,就是json格式,在使用springboot中进行数据的读取的时候往往会将json类型的数据直接转换成字符串类型的数据,对于页面的数据的处理很不友好,如何来将json类型的数据序列化成List或者Map类型的,七月老师提供了一整套的代码完成以及思考过程,记录一下整个代码的优化过程

    一、为什么要对这个进行优化?

    1、这块主要涉及的是sku表中的specs字段,这个字段的意义在于可以准确的确定是哪一件商品,比如:我需要的是(颜色:暗夜绿色,版本:256G全网通)的iPhone 11 Pro手机,其中暗夜绿色,全网通的iPhone 11 Pro手机就是一条sku数据,暗夜绿色,全网通版本就是specs字段所存储的内容,我们在数据库中是以json字段进行存储的,我们不做处理的话,返回给前端的就是json字符串,

    例如:"specs": "[{"key": "颜色", "value": "橘黄色", "key_id": 1, "value_id": 44}, {"key": "图案", "value": "七龙珠", "key_id": 3, "value_id": 9}, {"key": "尺码", "value": "小号 S", "key_id": 4, "value_id": 14}]"

    虽然前端也是可以处理的,但是后台我们进行序列化之后,再返回给前端不是更加友好吗?哈哈,真是贴心的后端开发者!!!
    2、最完美的返回形式
    "specs": [{"key_id": 1,"key": "颜色","value_id": 45, "value": "金属灰" },{"key_id": 3, "key": "图案","value_id": 9,"value": "七龙珠"},{"key_id": 4, "key": "尺码","value_id": 14,"value": "小号 S"}],
    这样的话,前端开发人员可以直接读取遍历出想要的数据

     二、单体Json对象的映射处理

    1、首先做一个单体Json对象与Map的转换的工具类

    注意:

    (1)json序列化工具用的是jackson

    (2)异常处理是抛出500错误,也就是服务器异常,做了一下异常处理的封装(这里是把必须要处理的IO异常。转换成RuntimeException)

    (3)一定要加上@Converter注解

     1 @Converter
     2 public class MapAndJson implements AttributeConverter<Map<String, Object>, String> {
     3 
     4     @Autowired
     5     private ObjectMapper mapper;
     6 
     7     @Override
     8     public String convertToDatabaseColumn(Map<String, Object> stringObjectMap) {
     9         try {
    10             return mapper.writeValueAsString(stringObjectMap);
    11         } catch (JsonProcessingException e) {
    12             e.printStackTrace();
    13             throw new ServerErrorException(9999);
    14         }
    15     }
    16 
    17     @Override
    18     public Map<String, Object> convertToEntityAttribute(String s) {
    19         try {
    20             if (s == null) {
    21                 return null;
    22             }
    23             return mapper.readValue(s, HashMap.class);
    24         } catch (JsonProcessingException e) {
    25             e.printStackTrace();
    26             throw new ServerErrorException(9999);
    27         }
    28     }
    29 }

    2、转换字段中使用

    1     @Convert(converter = MapAndJson.class)
    2     private Map<String, Object> test;

    三、数组类型json与List的映射

    1、首先做一个数组类型Json与List转换的工具类

    注意:这个工具类基本上和单体Json与Map映射很类似

     1 @Converter
     2 public class ListAndJson implements AttributeConverter<List<Object>, String> {
     3 
     4     @Autowired
     5     private ObjectMapper mapper;
     6 
     7     @Override
     8     public String convertToDatabaseColumn(List<Object> objects) {
     9         try {
    10             return mapper.writeValueAsString(objects);
    11         } catch (JsonProcessingException e) {
    12             e.printStackTrace();
    13             throw new ServerErrorException(9999);
    14         }
    15     }
    16 
    17     @Override
    18     public List<Object> convertToEntityAttribute(String s) {
    19         try {
    20             if (s == null) {
    21                 return null;
    22             }
    23             return mapper.readValue(s, List.class);
    24         } catch (JsonProcessingException e) {
    25             e.printStackTrace();
    26             throw new ServerErrorException(9999);
    27         }
    28     }
    29 
    30 }

    2、字段中使用

    1     @Convert(converter = ListAndJson.class)
    2     private List<Object> specs;

    四、更优的解决方案

    以上两个方法存在的问题是:没有办法确定具体的业务对象,就是一个Map,或者是List<Object>,没有办法确定到底是哪种业务对象,就像我们这里所要的,我们想要的是List<Spec>这种具体的Spec的对象的集合,这样的话,更加符合面向对象的思想,而且即使后面我们调用Spec具体对象中的业务方法的时候会更加方便,所以有必要做一个更加的优化方案!

    1、创建一个通用的序列化反序列化工具类

    注意:这里很不好理解的,只有对泛型比较熟悉,才能很容易理解,至于写出这种代码,我觉得目前还是写不出来的

     1 @Component
     2 public class GenericAndJson {
     3 
     4     private static ObjectMapper mapper;
     5 
     6     // 这里用到的set方法的自动注入,实例化static变量
     7     @Autowired
     8     public void setMapper(ObjectMapper mapper) {
     9         GenericAndJson.mapper = mapper;
    10     }
    11 
    12     public static <T> String objectToJson(T o) {
    13         try {
    14             return GenericAndJson.mapper.writeValueAsString(o);
    15         } catch (JsonProcessingException e) {
    16             e.printStackTrace();
    17             throw new ServerErrorException(9999);
    18         }
    19     }
    20 
    21     public static <T> T jsonToObject(String s, TypeReference<T> tr) {
    22         try {
    23             if (s == null) {
    24                 return null;
    25             }
    26             return GenericAndJson.mapper.readValue(s, tr);
    27         } catch (JsonProcessingException e) {
    28             e.printStackTrace();
    29             throw new ServerErrorException(9999);
    30         }
    31     }
    32 
    33 }

    2、实际中使用

    注意:需要重写变量的set与get方法,来进行序列化与反序列化操作

     1     private String specs;
     2 
     3     public List<Spec> getSpecs() {
     4         if(this.specs == null){
     5             return Collections.emptyList();
     6         }
     7         return GenericAndJson.jsonToObject(this.specs, new TypeReference<List<Spec>>() {
     8         });
     9     }
    10 
    11     public void setSpecs(List<Spec> specs) {
    12         if(specs.isEmpty()){
    13             return;
    14         }
    15         this.specs = GenericAndJson.objectToJson(specs);
    16     }

     内容出处:七月老师《从Java后端到全栈》视频课程

    七月老师课程链接:https://class.imooc.com/sale/javafullstack

  • 相关阅读:
    FJNU 1151 Fat Brother And Geometry(胖哥与几何)
    FJNU 1157 Fat Brother’s ruozhi magic(胖哥的弱智术)
    FJNU 1159 Fat Brother’s new way(胖哥的新姿势)
    HDU 3549 Flow Problem(最大流)
    HDU 1005 Number Sequence(数列)
    Tickets(基础DP)
    免费馅饼(基础DP)
    Super Jumping! Jumping! Jumping!(基础DP)
    Ignatius and the Princess IV(基础DP)
    Keywords Search(AC自动机)
  • 原文地址:https://www.cnblogs.com/ssh-html/p/12688172.html
Copyright © 2011-2022 走看看