让我们假设,我们有一个像这样的bean:
public class Response<T> {
private T data;
private double executionDuration;
private boolean success;
private String version;
//HOW TO Make Jackson to inject this?
private Class<T> dataClass;
public Optional<T> getData() {
return Optional.ofNullable(data);
}
public double getExecutionDuration() {
return executionDuration;
}
public Class<T> getDataClass() {
return dataClass;
}
public String getVersion() {
return version;
}
public boolean isSuccess() {
return success;
}
}
反序列化的过程如下:
objectMapper.readValue(json, new TypeReference<Response<SomeClass>>() {});
我可以以某种方式让Jackson将类“ SomeClass”注入到我的bean中吗?我认为,注入类型引用本身也是可以的。
答案 0 :(得分:1)
这对我有用;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
public class Entity<T> {
private T data;
@JsonSerialize(converter = ClassToStringConverter.class)
@JsonDeserialize(converter = StringToClassConverter.class)
private Class<T> dataClass;
}
和
import com.fasterxml.jackson.databind.util.StdConverter;
public class ClassToStringConverter extends StdConverter<Class<?>, String> {
public String convert(Class<?> aClass) {
// class java.lang.Integer
return aClass.toString().split("\\s")[1];
}
}
和
import com.fasterxml.jackson.databind.util.StdConverter;
public class StringToClassConverter extends StdConverter<String, Class<?>> {
public Class<?> convert(String s) {
try {
return Class.forName(s);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
主要;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
Entity<Integer> data = new Entity<Integer>();
data.setData(5);
data.setDataClass(Integer.class);
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(data);
Entity<Integer> jsonData = mapper.readValue(json, new TypeReference<Entity<Integer>>() {});
System.out.println(jsonData.getData());
System.out.println(jsonData.getDataClass().getCanonicalName());
}
}
但是,也许不保存类类型而是使用方法从数据中获取类型会更好吗?
public Class<T> getType() {
return (Class<T>) data.getClass();
}
答案 1 :(得分:0)
如果不希望将类信息保存在json中并使用@JsonTypeInfo
,我建议使用@JacksonInject
:
public class Response<T> {
private T data;
private double executionDuration;
private boolean success;
private String version;
@JacksonInject("dataClass")
private Class<T> dataClass;
public Optional<T> getData() {
return Optional.ofNullable(data);
}
public double getExecutionDuration() {
return executionDuration;
}
public Class<T> getDataClass() {
return dataClass;
}
public String getVersion() {
return version;
}
public boolean isSuccess() {
return success;
}
}
反序列化看起来像:
ObjectMapper mapper = new ObjectMapper();
InjectableValues.Std injectable = new InjectableValues.Std();
injectable.addValue("dataClass", SomeClass.class);
mapper.setInjectableValues(injectable);
final Response<Integer> response = mapper.readValue(json, new TypeReference<Response<SomeClass>>() { });
答案 2 :(得分:0)
public class Response<T> {
private T data;
// other fields & methods
public Class getType() {
return Optional.ofNullable(data).map(Object::getClass).orElse(Void.class);
}
public Optional<Class> getSafeType() {
return Optional.ofNullable(data).map(Object::getClass);
}
}
超级简单,无需修补Jackson,NPE
安全...