Java – for a class that uses Jackson to execute collection, deserialization fails

I have the following JSON:

{
  "item": [
    { "foo": 1 },{ "foo": 2 }
  ]
}

This is basically an object that contains a collection of items

So I did a deserialization class:

public class ItemList {
  @JsonProperty("item")
  List<Item> items;

  // Getters,setters & co.
  // ...
}

Everything is fine until now

Now, in order to make my life easier elsewhere, I decided it would be good to iterate over the itemlist object and let it implement the collection interface

So basically my class became:

public class ItemList implements Collection<Item>,Iterable<Item> {
  @JsonProperty("item")
  List<Item> items;

  // Getters,setters & co.

  // Generated all method delegates to items. For instance:
  public Item get(int position) {
    return items.get(position);
  }
}

The implementation works normally, very well However, deserialization has now failed

Jackson seemed confused:

I tried to add @ jsondeserialize (as = itemlist. Class), but I didn't

What can I do?

Solution

Obviously, it doesn't work because Jackson uses the standard collection deserializer as the Java collection type, and they know nothing about the itemlist property

It can make it work, but not in a very elegant way You need to configure objectmapper to replace the default collection deserializer on the manually created bean deserializer of the corresponding type I have written an example to do this in beandeserializermodifier for all classes that use custom annotations

Note that I have to override objectmapper to access objectmapper's protected method createserializationcontext to create the appropriate deserialization context because the bean modifier cannot access it

This is the code:

public class JacksonCustomList {
    public static final String JSON = "{\n" +
            "  \"item\": [\n" +
            "    { \"foo\": 1 },\n" +
            "    { \"foo\": 2 }\n" +
            "  ]\n" +
            "} ";

    @Retention(RetentionPolicy.RUNTIME)
    public static @interface PreferBeanDeserializer {

    }

    public static class Item {
        public int foo;

        @Override
        public String toString() {
            return String.valueOf(foo);
        }
    }

    @PreferBeanDeserializer
    public static class ItemList extends ArrayList<Item> {
        @JsonProperty("item")
        public List<Item> items;

        @Override
        public String toString() {
            return items.toString();
        }
    }

    public static class Modifier extends BeanDeserializerModifier {
        private final MyObjectMapper mapper;

        public Modifier(final MyObjectMapper mapper) {
            this.mapper = mapper;
        }

        @Override
        public JsonDeserializer<?> modifyCollectionDeserializer(
                final DeserializationConfig config,final CollectionType type,final BeanDescription beanDesc,final JsonDeserializer<?> deserializer) {
            if (type.getRawClass().getAnnotation(PreferBeanDeserializer.class) != null) {
                DeserializationContext context = mapper.createContext(config);
                try {
                    return context.getFactory().createBeanDeserializer(context,type,beanDesc);
                } catch (JsonMappingException e) {
                   throw new IllegalStateException(e);
                }

            }
            return super.modifyCollectionDeserializer(config,beanDesc,deserializer);
        }
    }

    public static class MyObjectMapper extends ObjectMapper {
        public DeserializationContext createContext(final DeserializationConfig cfg) {
            return super.createDeserializationContext(getDeserializationContext().getParser(),cfg);
        }
    }

    public static void main(String[] args) throws IOException {
        final MyObjectMapper mapper = new MyObjectMapper();
        SimpleModule module = new SimpleModule();
        module.setDeserializerModifier(new Modifier(mapper));

        mapper.registerModule(module);
        System.out.println(mapper.readValue(JSON,ItemList.class));
    }

}
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>