首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >GenericJackson2JsonRedisSerializer忽略类和属性

GenericJackson2JsonRedisSerializer忽略类和属性
EN

Stack Overflow用户
提问于 2021-01-07 20:24:03
回答 1查看 468关注 0票数 0

我正在尝试将ClassA序列化为JSON,然后反序列化并仅在相似属性上将其映射为ClassB,忽略了许多检查。比方说我有

代码语言:javascript
运行
复制
public class First{
   private String attribute1;
   private String attribute2;
   private String attribute3;
}

public class Second{
   private Int attribute1;
   private String attribute2;
   private String attribute4;
}

我期望的是映射Second的对象,如下所示

代码语言:javascript
运行
复制
{
   "attribute2": "value2"
}

有可能吗?我需要这样做,因为我在一些微服务之间有一个共享的redis缓存键。由于设计变更,redis中存储的类可能会有不同的定义,检查和更新每个微服务的代码是不可行的。谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-01-08 11:29:43

没有直接的方法来告诉GenericJackson2JsonRedisSerializer忽略某些字段并将类A强制转换为B,您可以实现任何您想要的反序列化策略。

一个简单的例子是,当你想进行类型转换时,你注册你的映射和可忽略的字段。

代码语言:javascript
运行
复制
// Adapted from spring data redis
public class RqueueRedisSerDes implements RedisSerializer<Object> {
    private ObjectMapper mapper;

    @AllArgsConstructor
    @Getter
    class Dataum {
      Class<?> tgtClass;
      String[] ignorableProperties;
    }

    private Map<Class<?>, Dataum> classMap = new ConcurrentHashMap<>();

    RqueueRedisSerDes() {
      this.mapper = new ObjectMapper();
      this.mapper =
          mapper.registerModule(new SimpleModule().addSerializer(new NullValueSerializer()));
      this.mapper = mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
      this.mapper = mapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY);
    }

    public void addClassMap(Class<?> source, Class<?> tgt, String[] ignorableProperties) {
      classMap.put(source, new Dataum(tgt, ignorableProperties));
    }

    @Override
    public byte[] serialize(Object source) throws SerializationException {
      if (source == null) {
        return SerializationUtils.EMPTY_ARRAY;
      }
      try {
        return mapper.writeValueAsBytes(source);
      } catch (JsonProcessingException e) {
        throw new SerializationException("Could not write JSON: " + e.getMessage(), e);
      }
    }

    @Override
    public Object deserialize(byte[] source) throws SerializationException {
      if (SerializationUtils.isEmpty(source)) {
        return null;
      }
      try {
        Object object = mapper.readValue(source, Object.class);
        for (Entry<Class<?>, Dataum> entry : classMap.entrySet()) {
          if (ClassUtils.isAssignable(entry.getKey(), object.getClass())) {
            Dataum dataum = entry.getValue();
            Object tgt = dataum.getTgtClass().newInstance();
            BeanUtils.copyProperties(object, tgt, dataum.getIgnorableProperties());
            return tgt;
          }
        }
        return object;
      } catch (Exception ex) {
        throw new SerializationException("Could not read JSON: " + ex.getMessage(), ex);
      }
    }

    private static class NullValueSerializer extends StdSerializer<NullValue> {

      private static final long serialVersionUID = 211020517180777825L;
      private final String classIdentifier;

      NullValueSerializer() {
        super(NullValue.class);
        this.classIdentifier = "@class";
      }

      @Override
      public void serialize(
          NullValue value, JsonGenerator jsonGenerator, SerializerProvider provider)
          throws IOException {
        jsonGenerator.writeStartObject();
        jsonGenerator.writeStringField(classIdentifier, NullValue.class.getName());
        jsonGenerator.writeEndObject();
      }
    }
  }

定义一个实现RedisSerializer<Object>的类,在RedisConnectionFactory中使用这个类来序列化/反序列化值。

代码语言:javascript
运行
复制
class SerializerTest{      
  @Data
  @AllArgsConstructor
  @NoArgsConstructor
  public static class First {
    private String attribute1;
    private String attribute2;
    private String attribute3;
  }
  @Data
  @ToString
  public static class Second {
    private Integer attribute1;
    private String attribute2;
    private String attribute4;
  }

  public static void main(String[] args) {
    RqueueRedisSerDes serDes = new RqueueRedisSerDes();
    // ignore attribute1 due to different type
    serDes.addClassMap(First.class, Second.class, new String[]{"attribute1"});
    First first = new First("1", "2", "3");
    byte[] out = serDes.serialize(first);
    Second second = (Second) serDes.deserialize(out);
    System.out.println(second);
  }
}

我刚刚修改了我的回购Rqueue中的代码

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65612342

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档