java Jackson,如何正确编写自定义反序列化程序
我正在尝试从Gson迁移到Jackson,但我遇到了很多困难,因为我不太了解如何反序列化复杂的JSON
文件如下所示:
{
"data_type": "DatType1",
"data": {
"data_array": [
{
"data_type": "DataType2",
"data": {
"prop1": "AString",
"prop2": ALongValue,
"prop3": null,
"prop4": "AString",
}
},
{
"data_type": "DataType2",
"data": {
"prop1": "AString",
"prop2": ALongValue,
"prop3": "AString",
"prop4": null,
}
}
]
}
}
我试图编写这个自定义反序列化程序:
public class DataListDeserializer extends StdDeserializer<DataList> {
public DataListDeserializer() {
this(null);
}
public DataListDeserializer(Class<?> vc) {
super(vc);
}
@Override
public DataList deserialize(JsonParser parser, DeserializationContext context) throws IOException {
JsonNode node = parser.getCodec().readTree(parser);
DataTypeEnum type = DataTypeEnum.from(node.get("data_type").asText());
JsonNode dataNode = node.get("data");
JsonParser ps = dataNode.findValue("data_array").traverse();
ps.setCodec(parser.getCodec());
List<Data2> trophies = ps.readValueAs(new TypeReference<List<Data2>>() {});
return null; // Ignore null I'm using the debugger to check
}
}
但是反序列化的Data2对象具有所有字段null
另外,最后我应该用解析后的类型和Data2 list构建一个DataList对象,但我不能使用构造函数,因为我需要它是私有的,这个对象是不可变的
我该怎么做
注:
使用Gson时,我没有编写任何反序列化程序,因为我使用的是JsonPath来获取嵌套对象。我正在使用这个带有自定义注释的TyeAdapterFactory:
public final class JsonPathTypeAdapterFactory implements TypeAdapterFactory {
//================================================================================
// Properties
//================================================================================
private static final TypeAdapterFactory jsonPathTypeAdapterFactory = new JsonPathTypeAdapterFactory();
//================================================================================
// Constructors
//================================================================================
private JsonPathTypeAdapterFactory() {
}
//================================================================================
// Getters
//================================================================================
public static TypeAdapterFactory getJsonPathTypeAdapterFactory() {
return jsonPathTypeAdapterFactory;
}
//================================================================================
// Override Methods
//================================================================================
@Override
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
final TypeAdapter<T> delegateAdapter = gson.getDelegateAdapter(this, typeToken);
final Collection<FieldInfo> fieldInfos = FieldInfo.of(new ArrayList<>(), typeToken.getRawType());
return fieldInfos.isEmpty() ? delegateAdapter : new JsonPathTypeAdapter<>(gson, delegateAdapter, gson.getAdapter(JsonElement.class), fieldInfos);
}
//================================================================================
// Nested Classes
//================================================================================
private static final class JsonPathTypeAdapter<T> extends TypeAdapter<T> {
private final Gson gson;
private final TypeAdapter<T> delegateAdapter;
private final TypeAdapter<JsonElement> jsonElementTypeAdapter;
private final Collection<FieldInfo> fieldInfos;
private JsonPathTypeAdapter(final Gson gson, final TypeAdapter<T> delegateAdapter, final TypeAdapter<JsonElement> jsonElementTypeAdapter, final Collection<FieldInfo> fieldInfos) {
this.gson = gson;
this.delegateAdapter = delegateAdapter;
this.jsonElementTypeAdapter = jsonElementTypeAdapter;
this.fieldInfos = fieldInfos;
}
@Override
public void write(final JsonWriter out, final T value) throws IOException {
delegateAdapter.write(out, value);
}
@Override
public T read(final JsonReader in) throws IOException {
final JsonElement outerJsonElement = jsonElementTypeAdapter.read(in).getAsJsonObject();
final T value = delegateAdapter.fromJsonTree(outerJsonElement);
for (final FieldInfo fieldInfo : fieldInfos) {
try {
final JsonElement innerJsonElement = fieldInfo.jsonPath.read(outerJsonElement);
final Object innerValue = gson.fromJson(innerJsonElement, fieldInfo.field.getType());
fieldInfo.field.set(value, innerValue);
} catch (final PathNotFoundException ignored) {
} catch (final IllegalAccessException ex) {
throw new IOException(ex);
}
}
return value;
}
}
private static final class FieldInfo {
private final Field field;
private final JsonPath jsonPath;
private FieldInfo(final Field field, final JsonPath jsonPath) {
this.field = field;
this.jsonPath = jsonPath;
}
private static Collection<FieldInfo> of(Collection<FieldInfo> fieldInfo, Class<?> clazz) {
fieldInfo.addAll(
Arrays.stream(clazz.getDeclaredFields())
.filter(f -> f.getAnnotation(JsonPathExpression.class) != null)
.map(f -> {
final JsonPathExpression jsonPathExpression = f.getAnnotation(JsonPathExpression.class);
f.setAccessible(true);
return new FieldInfo(f, compile(jsonPathExpression.value()));
})
.collect(Collectors.toList())
);
if (clazz.getSuperclass() != null) {
of(fieldInfo, clazz.getSuperclass());
}
return fieldInfo;
}
}
}
事实上,这很好,很容易,但我不认为有办法让杰克逊也这么做,不是吗
共 (0) 个答案