有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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) 个答案