4

关于Redis的问题探讨(二):Range方法返回的对象是LinkeHashMap以及转换办法 - LonZyua...

 2 years ago
source link: https://www.cnblogs.com/kzyuan/p/16312931.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

关于Redis的问题探讨(二):Range方法返回的对象是LinkeHashMap以及转换办法

上一篇:关于Redis的问题探讨(一):为何存放集合偏向于转String后存放而非直接存

在上篇中发现了一个问题,明明存的是一个对象的集合,为什么通过range方法返回的却是LinkeHashMap

于是通过debug看看源码,了解执行流程,找一下原因

这是笔者通过debug画出的大致流程:

1957622-20220526113856524-1028467396.png

注意看8中,mapObject方法,这里就是返回LinkeHashMap的原因,这里重点解析一下mapObject方法:

protected Object mapObject(JsonParser p, DeserializationContext ctxt) throws IOException {
       // 获取字段名称,也就是key String key1 = p.getText();
       // 执行前该token是FIELD_NAME,也就是字段名称
       // 然后执行nextToken()后,变为了VALUE_STRING,也就是String类型的字段值
       // 但是如果值不为String类型,那就会在后面又执行一次nextToken,变为VALUE_NUMBER_INT,也就是整数型字段值 p.nextToken(); Object value1 = this.deserialize(p, ctxt); String key2 = p.nextFieldName(); if (key2 == null) { LinkedHashMap<String, Object> result = new LinkedHashMap(2); result.put(key1, value1); return result; } else {
          // 解释在上面 p.nextToken();
          // 获取value值 Object value2 = this.deserialize(p, ctxt); String key = p.nextFieldName(); LinkedHashMap result; if (key == null) { result = new LinkedHashMap(4); result.put(key1, value1); result.put(key2, value2); return result; } else { result = new LinkedHashMap(); result.put(key1, value1); result.put(key2, value2); do { p.nextToken(); result.put(key, this.deserialize(p, ctxt)); } while((key = p.nextFieldName()) != null); return result; } } }

首先就是这个p也就是JsonParser对象,他是通过JsonFactory的createParser方法创建的,其作用是解析Json字符串,因此在执行之前mapObject之前就已经将value解析并存入JsonParser中了。

JsonParser解释参考:https://blog.csdn.net/LBWNB_Java/article/details/120003565

然后执行流程可以参考注释

以上就是为何返回LinkeHashMap的原因,那么如何解决呢

这里就要用到ObjectMapper,在range方法的流程图中也看到其实也使用了他

通过ObjectMapper的convertValue方法将LinkeHashMap转为目标对象:

@Test
    public void testRange() {
        String key = "right_push_all_01";
        List<LinkedHashMap<String, Object>> linkedHashMapList = redisService.lRange(key, 0, -1);
        ObjectMapper objectMapper = new ObjectMapper();
        List<ThisIsDTO> thisIsDTOList = objectMapper.convertValue(linkedHashMapList, new TypeReference<List<ThisIsDTO>>() {
        });
        for (ThisIsDTO thisIsDTO : thisIsDTOList) {
            System.out.println(thisIsDTO.getAge());
        }
    }

注意:因为是集合存放,所以一定要new TypeReference<List<ThisIsDTO>>来定义转换的类型

如果只是单个对象,可以直接 objectMapper.convertValue(linkedHashMap, ThisIsDTO.class)

运行测试:

1957622-20220526113600509-1973242727.png

 可以发现转换成功了


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK