java 使用 Jackson 自定义反序列化列表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34176607/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 22:34:23  来源:igfitidea点击:

Custom deserialization of List using Hymanson

javajsonHymansondeserialization

提问by D.Razvan

I am trying to write a custom deserializer in order to trim down a big set of data I receive from somewhere else. I return a List of custom objects from the deserializer.

我正在尝试编写一个自定义反序列化器,以减少我从其他地方收到的大量数据。我从反序列化器返回一个自定义对象列表。

My question is, how do I do that, if this is my custom deserializer :

我的问题是,如果这是我的自定义解串器,我该怎么做:

public class MyCustomDeserializer extends JsonDeserializer<List<CustomClass>> { ... }

I certainly can't do this :

我当然不能这样做:

final SimpleModule module = new SimpleModule();
module.addDeserializer(List<CustomClass>.class, new MyCustomDeserializer());

Will something like this work ?

像这样的东西会起作用吗?

final List<CustomClass> response = Arrays.asList(objectMapper.readValue(stringBean, CustomClass[].class));

If this indeed works, I find it a bit confusing and "dangerous" ? Isn't the deserialization done inside the asList method invocation ? So it basically maps a List to an array[] ?

如果这确实有效,我觉得它有点混乱和“危险”?反序列化不是在 asList 方法调用中完成的吗?所以它基本上将一个 List 映射到一个 array[] ?

I learned about TypeReference so I can probably use that like so :

我了解了 TypeReference,所以我可以像这样使用它:

objectMapper.readValue(stringBean, new TypeReference<List<CustomClass>>(){});

but I heard it is slower.

但我听说它更慢。

I also don't want to create a container for the list, and return that in the deserialization because that means it will be wrapped in another json object, and I simply want my endpoint to produce something like :

我也不想为列表创建一个容器,并在反序列化中返回它,因为这意味着它将被包装在另一个 json 对象中,我只是希望我的端点产生类似的东西:

[{object1}, {object2}]

// instead of

{"Output" : [{object1}, {object2}]}

EDIT:

编辑:

It seems that I have misinterpreted how Hymanson is using my deserializer in both cases :

似乎我误解了 Hymanson 在这两种情况下如何使用我的解串器:

final List<CustomClass> response = Arrays.asList(objectMapper.readValue(stringBean, CustomClass[].class));
// or
objectMapper.readValue(stringBean, new TypeReference<List<CustomClass>>(){});

It looks like the deserializer is called twice, once for each object in the array. I thought that the entire array would be considered as a whole. To clear the confusion, here is what I mean:

看起来反序列化器被调用了两次,一次是为数组中的每个对象调用一次。我认为整个阵列会被视为一个整体。为了消除混淆,我的意思是:

The json I receive and try to deserialize looks like so :

我收到并尝试反序列化的 json 如下所示:

[
  {
    "Data" : {
      "id" : "someId",
      "otherThing" : "someOtherThing"
    },
    "Message" : "OK"
  },
  {
    "Data" : null,
    "Message" : "Object not found for id blabla"
  }
]

and so I though this is what I would have inside my deserializer, but as I said before it seems that i actually get each "entry" from that array and call it multiple times.

所以我虽然这就是我的解串器中的内容,但正如我之前所说的那样,我似乎实际上从该数组中获取了每个“条目”并多次调用它。

回答by Sharon Ben Asher

First of all, If you registered your custom deserializer using annotation on the bean CustomClassthen the deserializer should handle one instance of CustomClassand not a collection and thus should be defined:

首先,如果您使用 bean 上的注释注册了自定义反序列化器,CustomClass那么反序列化器应该处理一个实例CustomClass而不是集合,因此应该定义:

public class MyCustomDeserializer extends JsonDeserializer<CustomClass> {
        @Override
        public CustomClass deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException
        {
            ...
        }
}

and now you can use Hymanson's type factory to pass the mapper the required type information

现在您可以使用 Hymanson 的类型工厂向映射器传递所需的类型信息

JavaType customClassCollection = objectMapper.getTypeFactory().constructCollectionType(List.class, CustomClass.class);
List<CustomClass> beanList = (List<CustomClass>)objectMapper.readValue(stringBean, customClassCollection);