Няма директен начин да кажете на 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);
}
}
Току-що промених код от моята Repo Rqueue