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

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

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

JavaType customClassCollection = objectMapper.getTypeFactory().constructCollectionType(List.class, CustomClass.class);
List<CustomClass> beanList = (List<CustomClass>)objectMapper.readValue(stringBean, customClassCollection);
Answer from Sharon Ben Asher on Stack Overflow
🌐
Baeldung
baeldung.com › home › json › jackson › getting started with custom deserialization in jackson
Getting Started with Custom Deserialization in Jackson
September 3, 2024 - As we can see, the deserializer is working with the standard Jackson representation of JSON — the JsonNode. Once the input JSON is represented as a JsonNode, we can now extract the relevant information from it and construct our own Item entity. Simply put, we need to register this custom deserializer and deserialize the JSON normally:
Discussions

Trying to deserialize a json array using a Jackson custom deserializer
ContactsCustomDeserializer.java line 43 you're calling the wrong Contacts constructor. You're calling Contacts line 19 which does not set the contacts property. Delete construction on line 19, use the other construction in ContactsCustomDeserializer and pass an instance of the collection type you want. Or delete constructor on line 15 and initialize the collection to new ArrayList() or new HashSet() or whatever's appropriate. More on reddit.com
🌐 r/learnjava
3
2
June 9, 2022
java - Custom deserializer for any list in Jackson - Stack Overflow
I have a problem with wrong objects in lists. For instance I've a JSON model: { "items": [ { "id": 1, "name": "Item1" }, { "id": 2, "name": "Item2" }, { "id": [], "name": "Item3" } ] } ... com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.Integer ... More on stackoverflow.com
🌐 stackoverflow.com
April 26, 2017
java - How to define a generic list deserializer through annotations with Jackson? - Stack Overflow
I'm looking for a way to create a "generic" deserializer — one that would be able to deserialize both types of lists, similar to ContextualDeserializer for mapping JSON to different types of maps with Jackson. The final purpose is to implement custom deserializing logic in MyListDeserializer ... More on stackoverflow.com
🌐 stackoverflow.com
java - Custom JSON Deserialization with Jackson - Stack Overflow
Another advantage of this solution is, that my domain class (FlickrAccount) is not polluted with any Jackson annotations. Based on @Michał Ziober's answer, I decided to use the - in my opinion - most straight forward solution. Using a @JsonDeserialize annotation with a custom deserializer: More on stackoverflow.com
🌐 stackoverflow.com
🌐
Mkyong
mkyong.com › home › java › jackson custom serializer and deserializer examples
Jackson Custom Serializer and Deserializer Examples | mkyong.com
May 6, 2024 - The following example creates a custom deserializer to convert the JSON field that contains dates as strings, and we want to convert them to the Localdate type. ... package com.mkyong.json.jackson.tips; import com.fasterxml.jackson.core.Jac...
🌐
GitHub
gist.github.com › kashyapp › 5132236
Jackson Custom Deserializer - pick up only keys of map and return as list. · GitHub
Jackson Custom Deserializer - pick up only keys of map and return as list. - jackson-custom-serializer.java
🌐
Medium
cowtowncoder.medium.com › jackson-tips-custom-list-serialization-4566f734c58d
Jackson Tips: custom List serialization | by @cowtowncoder | Medium
May 31, 2021 - This approach definitely has its limits, and its a bit intrusive (since we need to expose our new type — fortunately with default constructor, it should work just fine for deserialization too) — but it works wonders for a relatively common case of List (or Sets, Collections and Maps) with simple scalar values, but with some processing requirements. For example:
🌐
Medium
orashar.medium.com › unlocking-the-power-of-jackson-custom-serializers-and-deserializers-in-kotlinunlocking-the-power-a5325f3ef4b5
Unlocking the Power of Jackson: Custom Serializers and Deserializers in Java/Kotlin | by Om Parashar | Medium
May 16, 2023 - We want to serialize the list of users into a JSON object where the keys are user IDs and the values are the role names. On the other hand, when deserializing the JSON object, we want to map the role names back to their corresponding role IDs.
🌐
Reddit
reddit.com › r/learnjava › trying to deserialize a json array using a jackson custom deserializer
r/learnjava on Reddit: Trying to deserialize a json array using a Jackson custom deserializer
June 9, 2022 -

I am getting a null pointer exception when trying to run the program.

Cannot invoke "java.util.Collection.add(Object)" because "this.contacts" is null
java.lang.NullPointerException: Cannot invoke "java.util.Collection.add(Object)" because "this.contacts" is null

I have a json file that is structured like this:

{
  "id": 1,
  "name": {
    "first": "Yong",
    "last": "Mook Kim"
  },
  "contact": [
    {
      "type": "phone/home",
      "ref": "111-111-1234"
    },
    {
      "type": "phone/work",
      "ref": "222-222-2222"
    }
  ]
}

ContactsCustomDeserializer.java

package jacksontreedeserializer;

import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import jacksontree.Contact;
import jacksontree.Contacts;
import java.io.IOException;

public class ContactsCustomDeserializer extends StdDeserializer<Contacts>  {



    public ContactsCustomDeserializer(){

        this(null);

    }

    public ContactsCustomDeserializer(Class clz){
        super(clz);
    }



    @Override
    public Contacts deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException, JacksonException {

        Contacts contacts = new Contacts();
        try {
            JsonNode root = parser.getCodec().readTree(parser);
            JsonNode contactRoot = root.path("contact");

            if(contactRoot.isArray()){
                for(JsonNode node: contactRoot){
                    String type = node.path("type").asText();
                    String ref = node.path("red").asText();
                    Contact contact = new Contact(type,ref);
                    contacts.addContact(contact);

                }

            }

        }


        catch(JsonGenerationException e){
            e.printStackTrace();
        }

        return contacts;

    }
}

Contact.java

package jacksontree;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import jacksontreedeserializer.ContactsCustomDeserializer;

public class Contact {


    @JsonProperty("type")
    private String type;


    @JsonProperty("ref")
    private String ref;


    public Contact() {}

    public Contact(String type, String ref) {
        this.type = type;
        this.ref = ref;
    }

    @Override
    public String toString() {
        return "Contact{" +
                "type='" + type + '\'' +
                ", ref='" + ref + '\'' +
                '}';
    }





}

Contacts.java

package jacksontree;

import com.fasterxml.jackson.annotation.JsonProperty;

import java.util.Collection;
import java.util.List;

public class Contacts {


    @JsonProperty("contacts")
    private Collection<Contact> contacts;


    public Contacts(Collection<Contact> contacts){
        this.contacts = contacts;
    }

    public Contacts(){}


    public void addContact(Contact contact){
        contacts.add(contact);
    }


    @Override
    public String toString() {
        return "Contacts{" +
                "contacts=" + contacts +
                '}';
    }

}

Main.java

   @Test
    void deserialize() throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addDeserializer(Contacts.class, new ContactsCustomDeserializer());
        objectMapper.registerModule(simpleModule);
        Contacts contacts = objectMapper.readValue(new File("/Users/foo/Downloads/LearningJackson/src/main/resources/data/user.json"), Contacts.class);
        System.out.println(contacts);


    }
Top answer
1 of 2
2
ContactsCustomDeserializer.java line 43 you're calling the wrong Contacts constructor. You're calling Contacts line 19 which does not set the contacts property. Delete construction on line 19, use the other construction in ContactsCustomDeserializer and pass an instance of the collection type you want. Or delete constructor on line 15 and initialize the collection to new ArrayList() or new HashSet() or whatever's appropriate.
2 of 2
1
Please ensure that: Your code is properly formatted as code block - see the sidebar (About on mobile) for instructions You include any and all error messages in full - best also formatted as code block You ask clear questions You demonstrate effort in solving your question/problem - plain posting your assignments is forbidden (and such posts will be removed) as is asking for or giving solutions. If any of the above points is not met, your post can and will be removed without further warning. Code is to be formatted as code block (old reddit/markdown editor: empty line before the code, each code line indented by 4 spaces, new reddit: https://imgur.com/a/fgoFFis ) or linked via an external code hoster, like pastebin.com, github gist, github, bitbucket, gitlab, etc. Please, do not use triple backticks (```) as they will only render properly on new reddit, not on old reddit. Code blocks look like this: public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!"); } } You do not need to repost unless your post has been removed by a moderator. Just use the edit function of reddit to make sure your post complies with the above. If your post has remained in violation of these rules for a prolonged period of time (at least an hour), a moderator may remove it at their discretion. In this case, they will comment with an explanation on why it has been removed, and you will be required to resubmit the entire post following the proper procedures. To potential helpers Please, do not help if any of the above points are not met, rather report the post. We are trying to improve the quality of posts here. In helping people who can't be bothered to comply with the above points, you are doing the community a disservice. I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.
🌐
Medium
medium.com › @rajdeepify › custom-deserialization-using-jackson-7303be55dc34
Custom Deserialization using Jackson | by Rajdeep Saha | Medium
August 25, 2023 - It may happen that the API response is deprecated and contains values that are invalid or has fields that do not exist in our Java object. In such cases, we can use a custom deserializer to handle the response to be correctly mapped to the POJO according to our requirement. Consider the following example of a Transaction class:
Find elsewhere
🌐
DZone
dzone.com › coding › languages › custom json deserialization with jackson
Custom JSON Deserialization With Jackson
December 17, 2015 - In such a case, you need to write a custom deserializer: import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.ObjectCodec; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import java.io.IOException; public class ProgramDeserializer extends JsonDeserializer<Program> { @Override public Program deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { O
Top answer
1 of 2
2

You can write a custom deserializer and implement deserialization logic in it, e.g.:

class ItemIdDeserialiser extends JsonDeserializer<Integer> {

    @Override
    public Integer deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        Object value = p.getCurrentValue();
        //Check if it's Integer
        if(value instanceof Integer){
            return (Integer) value;
        }
        return null; //Or return first element if it's a non empty list
    }
}

Once this is done, you can annotate the field with @JsonDeserialise to instruct jackson to use your class, e.g.:

class Item {

    @JsonDeserialize(using = ItemIdDeserialiser.class)
    private Integer id;
}

Update

If you just want to ignore the field in serialization/deserialization then you can annotate it with @JsonIgnore, e.g.

class Item {

        @JsonIgnore
        private Integer id;
    }

Or even better, remove id from pojo and add @JsonIgnoreProperties on the class, e.g.:

@JsonIgnoreProperties(ignoreUnknown = true)
class Item {

}

It will automatically ignore the properties which are present in json but not found in class.

2 of 2
1

You can use a "HidableSerializer" for this and check the data during serialization

1. Create a IHidable interface

The interface has a isHidden method which is called during serialization

package ch.hasselba.jackson.test;

public interface IHidable {
    public boolean isHidden();
}

2. Change your BadItem class

Add the interface and change the setter of id. When property id is deserialized, it is tested if it is an Integer. If not, the item is marked as bad.

package ch.hasselba.jackson.test;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties( {"hidden"} ) 
public class BadItem implements IHidable{
    private Integer id;
    public String name;
    private boolean isBadItem;
    public Integer getId(){
        return id;
    }
    public void setId(Object value){
        if( value instanceof Integer ){
            this.id = (Integer) value;
        }else{
            this.isBadItem = true;
        }
    }
    public boolean isHidden() {
        return isBadItem;
    }
}

3. Create a HidableSerializer

package ch.hasselba.jackson.test;

import java.io.IOException;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;


@SuppressWarnings("serial")
public class HidableSerializer<T> extends StdSerializer<T> {

    private JsonSerializer<T> defaultSerializer;

    protected HidableSerializer(Class<T> t) {
        super(t);
    }

    public JsonSerializer<T> getDefaultSerializer() {
        return defaultSerializer;
    }

    public void setDefaultSerializer(JsonSerializer<T> defaultSerializer) {
        this.defaultSerializer = defaultSerializer;
    }

    @Override
    public void serialize(T value, JsonGenerator jgen, SerializerProvider provider)
            throws IOException, JsonProcessingException {

        if( value instanceof IHidable ){
            IHidable hidableValue = (IHidable) value;
            if( hidableValue.isHidden() )
                return;
        }

        defaultSerializer.serialize(value, jgen, provider);
    }

}

4. Register the HidableSerializer and that's it

package ch.hasselba.jackson.test;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;

public class Demo {

    @SuppressWarnings("serial")
    public static void main(String[] args) {

        // register the HidableSerializer
        ObjectMapper mapper = new ObjectMapper();
        mapper.setSerializationInclusion(Include.NON_EMPTY);
        mapper.registerModule(new SimpleModule() {
            @Override
            public void setupModule(SetupContext context) {
                super.setupModule(context);
                context.addBeanSerializerModifier(new BeanSerializerModifier() {
                    @Override
                    public JsonSerializer<?> modifySerializer(
                      SerializationConfig config, BeanDescription desc, JsonSerializer<?> serializer) {
                        if (BadItem.class.isAssignableFrom(desc.getBeanClass())) {
                            HidableSerializer ser = new HidableSerializer(BadItem.class);
                            ser.setDefaultSerializer(serializer);
                            return ser;
                        }
                        return serializer;
                    }
                });
            }
        });

        String content = "{  \"items\": [    {      \"id\": 1,      \"name\": \"Item1\"    },    {      \"id\": 2,      \"name\": \"Item2\"    },    {      \"id\":[],      \"name\": \"Item3\"    }  ]}";

        // build the Object
        BadList test = null;
        try {
            test =  mapper.readValue(content, BadList.class);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // and now convert it back to a String
        String data = null;
        try {
             data = mapper.writeValueAsString(test);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // print the result
        System.out.println( data );
    }

}

When changing the id "[]" to an Integer value, the Item is displayed, otherwise it is empty.

The result:

{"items":[{"id":1,"name":"Item1"},{"id":2,"name":"Item2"}]}
🌐
Java Guides
javaguides.net › 2019 › 04 › jackson-list-set-and-map-serialization-and-deseialization-in-java-example.html
Jackson - List, Set and Map Serialization and Deserialization in Java Examples
April 24, 2019 - package net.javaguides.jackson; import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; /** * Using Jackson API for list serialization and deserialization * @author ramesh fadatare * */ public class JacksonListToJson { public static void main(String[] args) throws JsonProcessingException { // Create ObjectMapper object.
🌐
Thurloat
thurloat.com › 2012 › 05 › 05 › jackson-deserializing
Jackson Deserializing Polymorphic JSON - Adam Thurlow (Thurloat.com)
Reading and writing polymorphic data types using Jackson. For example a List<Key<Entity>> at runtime can only be recognized as List<?> due to Type Erasure with Generics so Jackson can really only try to serialize and deserialize that List as a list of POJOs.
🌐
ConcretePage
concretepage.com › jackson-api › jackson-custom-deserializer
Jackson Custom Deserializer
Here in our example, we will attach custom deserializer at class level. Find the example. Company.java · package com.concretepage; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; @JsonDeserialize(using= MyCustomDeserializer.class) public class Company { @JsonProperty("compId") private Integer id; @JsonProperty("compName") private String name; @JsonProperty("compAddress") private Address address; // } Now use ObjectMapper as following.
🌐
Rip Tutorial
riptutorial.com › custom json deserialization with jackson
Java Language Tutorial => Custom JSON Deserialization with Jackson
Jackson’s org.codehaus.jackson.map.ObjectMapper “just works” out of the box and we really don’t do anything in most cases. But sometimes we need custom deserializer to fulfill our custom needs and this tutorial will guide you through the process of creating your own custom deserializer.
🌐
Medium
bhavinshah7.medium.com › custom-deserialization-with-jackson-a0bb5a14c04b
Custom Deserialization with Jackson | by Bhavin Shah | Medium
June 8, 2024 - In the deserializeNode method, we use Jackson's DeserializationContext to find the appropriate deserializer for the nested BaseEntity object. This context manages references by maintaining a map of objects being deserialized. When the same object is encountered again, the context can provide the existing instance instead of creating a new one, thus preserving shared references. Here is an example JSON node string representing the incoming data over the wire.
🌐
HowToDoInJava
howtodoinjava.com › home › jackson › jackson – custom serializer and deserializer
Jackson - Custom Serializer and Deserializer
September 1, 2022 - Learn to create custom Jackson serializers and deserializers, register using the SimpleModule as well as @JsonSerialize and @JsonDeserialize.
Top answer
1 of 1
17

You can specify the deserializer class with which to deserialize the elements of the list with the contentUsing attribute of the @JsonDeserializer annotation.

public class Citizen {
    ...
    @JsonDeserializer(contentUsing=MyListDeserializer.class) 
    public void setTickets(List<Tickets> tickets) {
        this.tickets = tickets;
    }
}

Make your deserializer extend JsonDeserializer<BaseClass> and have a attribute in the BaseClass that stores the actual type of the concrete class.

abstract class BaseTickets {
    String ticketType;
    public String getTicketType()
}

public class MyListDeserializer extends JsonDeserializer<BaseTickets> {

    @Override
    public BaseTickets deserialize(JsonParser jsonParser, DeserializationContext arg1) throws IOException, JsonProcessingException {
        ObjectCodec oc = jsonParser.getCodec();
        JsonNode node = oc.readTree(jsonParser);
        Iterator<JsonNode> elements = node.getElements();
        for (; elements.hasNext();) {
            String type = (String) elements.next().get("ticketType");

            if (type.equals()){
               //create concrete type here
            }
        }
     }

Or if you want a single deserializer for all List types with no common base class, then use the using attribute, have MyListDeserializer extend JsonDeserialize<Object>. For determining the type of list element you would have to write a custom serializer that adds the type information to the list which can then be used in the generic deserializer.

public class Citizen {
    ...
    @JsonDeserializer(using=MyListDeserializer.class)
    @JsonSerializer(using=MyListSerializer.class) 
    public void setTickets(List<Tickets> tickets) {
        this.tickets = tickets;
    }
}

public class MyListSerializer extends JsonSerializer<Object> {

    @Override
    public void serialize(Object list, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
        @SuppressWarnings("rawtypes")
        jgen.writeStartObject();
        String type = getListType(list);
        jgen.writeStringField("listType", type);
        jgen.writeObjectField("list", list)
    }
}
Top answer
1 of 6
69

You can write custom deserializer for this class. It could look like this:

class FlickrAccountJsonDeserializer extends JsonDeserializer<FlickrAccount> {

    @Override
    public FlickrAccount deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        Root root = jp.readValueAs(Root.class);

        FlickrAccount account = new FlickrAccount();
        if (root != null && root.user != null) {
            account.setId(root.user.id);
            if (root.user.username != null) {
                account.setUsername(root.user.username.content);
            }
        }

        return account;
    }

    private static class Root {

        public User user;
        public String stat;
    }

    private static class User {

        public String id;
        public UserName username;
    }

    private static class UserName {

        @JsonProperty("_content")
        public String content;
    }
}

After that, you have to define a deserializer for your class. You can do this as follows:

@JsonDeserialize(using = FlickrAccountJsonDeserializer.class)
class FlickrAccount {
    ...
}
2 of 6
19

Since I don't want to implement a custom class (Username) just to map the username, I went with a little bit more elegant, but still quite ugly approach:

ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.readTree(in);
JsonNode user = node.get("user");
FlickrAccount account = new FlickrAccount();
account.setId(user.get("id").asText());
account.setUsername(user.get("username").get("_content").asText());

It's still not as elegant as I hoped, but at least I got rid of all the ugly casting. Another advantage of this solution is, that my domain class (FlickrAccount) is not polluted with any Jackson annotations.

Based on @Michał Ziober's answer, I decided to use the - in my opinion - most straight forward solution. Using a @JsonDeserialize annotation with a custom deserializer:

@JsonDeserialize( using = FlickrAccountDeserializer.class )
public class FlickrAccount {
    ...
}

But the deserializer does not use any internal classes, just the JsonNode as above:

class FlickrAccountDeserializer extends JsonDeserializer<FlickrAccount> {
    @Override
    public FlickrAccount deserialize(JsonParser jp, DeserializationContext ctxt) throws 
            IOException, JsonProcessingException {
        FlickrAccount account = new FlickrAccount();
        JsonNode node = jp.readValueAsTree();
        JsonNode user = node.get("user");
        account.setId(user.get("id").asText());
        account.setUsername(user.get("username").get("_content").asText());
        return account;
    }
}
🌐
GitHub
gist.github.com › 34fa91f8f6b9c46e25cb
Custom deserializer example in Jackson · GitHub
Custom deserializer example in Jackson · Raw · Bean.java · This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
🌐
Davismol
davismol.net › 2015 › 05 › 20 › jackson-create-a-custom-json-deserializer-with-stddeserializer-and-jsontoken-classes
Jackson: create a custom JSON deserializer with StdDeserializer and JsonToken classes | Dede Blog
May 20, 2015 - As we can see the representation of the original object is printed according to the redefined toString(), then the program prints the JSON string produced by our serializer, where we can find the list of elements represented as a single string with values separated by ‘;’ and finally the last part of the output is the representation of the SWEngineer object recreated through custom deserializer that properly coincides with that of the original object. The whole code of this example can be downloaded here: ... Pingback: Jackson: create and register a custom JSON serializer with StdSerializer and SimpleModule classes | Dede Blog