在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
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 |
请发表评论