我正在尝试将ClassA序列化为JSON,然后反序列化并仅在相似属性上将其映射为ClassB,忽略了许多检查。比方说我有
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
的对象,如下所示
{
"attribute2": "value2"
}
有可能吗?我需要这样做,因为我在一些微服务之间有一个共享的redis缓存键。由于设计变更,redis中存储的类可能会有不同的定义,检查和更新每个微服务的代码是不可行的。谢谢
发布于 2021-01-08 11:29:43
没有直接的方法来告诉GenericJackson2JsonRedisSerializer
忽略某些字段并将类A
强制转换为B
,您可以实现任何您想要的反序列化策略。
一个简单的例子是,当你想进行类型转换时,你注册你的映射和可忽略的字段。
// 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中使用这个类来序列化/反序列化值。
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中的代码
https://stackoverflow.com/questions/65612342
复制相似问题