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

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
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 - How to create a custom deserializer in Jackson for a List containing generic type? - Stack Overflow
Hi following this question How to create a custom deserializer in Jackson for a generic type? I would like to know how to adopt this to be able parse public static class Something { public static More on stackoverflow.com
🌐 stackoverflow.com
February 24, 2021
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
🌐
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.JacksonException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import java.io.IOException; import java.time.LocalDate; import java.time.format.DateTimeFormatter; public class LocalDateDeserializer extends JsonDeserializer<LocalDate> { private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); @Override public LocalDate deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { return LocalDate.parse(p.getValueAsString(), formatter); } }
🌐
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 - It is certainly possible to register serializers and deserializers for structured types, too, using Jackson Modules, but you do need to implement Serializers provider if taking that route. But how about using @JsonSerialize annotation? Turns out that works pretty well for our hypothetical use case. So, let’s consider a case that I know has been requested as a feature (but not yet implemented as such): ability to make contents of a List to be serialized in their natural (for Strings, lexicographic (~= alphabetic)) order:
🌐
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
🌐
Medium
medium.com › @rajdeepify › custom-deserialization-using-jackson-7303be55dc34
Custom Deserialization using Jackson | by Rajdeep Saha | Medium
August 25, 2023 - com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.util.Currency` from String “ABC”: not a valid textual representation · To handle a scenario like this where we want to conditionally ignore an invalid field, instead of discarding the entire response we can use a custom deserializer for our Currency class.
🌐
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 - The @JsonDeserialize annotation is used to specify a custom deserializer for a field or class. Deserializers in Jackson are responsible for converting JSON representations back into Java objects.
Find elsewhere
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"}]}
🌐
Thurloat
thurloat.com › 2012 › 05 › 05 › jackson-deserializing
Jackson Deserializing Polymorphic JSON - Adam Thurlow (Thurloat.com)
In this case it was used to read the JsonParser value in as the basic type in which it is serialized a List<Integer>, then create the Key objects out of them and return that. Then you simply add the @JsonDeserialize annotation to the model attribute which needs it and Jackson will go back to working flawlessly.
🌐
Spring
docs.spring.io › spring-data › rest › reference › customizing › custom-jackson-deserialization.html
Adding Custom Serializers and Deserializers to Jackson’s ObjectMapper :: Spring Data REST
public class MyCustomModule extends SimpleModule { … @Override public void setupModule(SetupContext context) { SimpleSerializers serializers = new SimpleSerializers(); SimpleDeserializers deserializers = new SimpleDeserializers(); serializers.addSerializer(MyEntity.class, new MyEntitySerializer()); deserializers.addDeserializer(MyEntity.class, new MyEntityDeserializer()); context.addSerializers(serializers); context.addDeserializers(deserializers); } } Thanks to the custom module shown in the preceding example, Spring Data REST correctly handles your domain objects when they are too complex for the 80% generic use case that Spring Data REST tries to cover.
🌐
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.
🌐
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.
🌐
LinkedIn
linkedin.com › pulse › java-records-jackson-custom-deserializers-dexter-legaspi
Java Records and Jackson Custom Deserializers
December 25, 2022 - public class CustomAdmantDeserializer extends StdDeserializer<Admant> { protected CustomAdmantDeserializer(Class<?> vc) { super(vc); } protected CustomAdmantDeserializer() { this(null); } @Override public Admant deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { JsonNode node = jsonParser.getCodec().readTree(jsonParser); var uniqueId = node.get("unique_id").asText(); var segmentId = node.get("ias_code").asText(); var name = node.get("name").asText(); var team = node.get("team").asText(); var teamGroups = StreamSupport .stream(node.get("team_groups").spliterator(), false) .map(JsonNode::asText) .toList(); assert node.get("targeting") != null; var segmentType = decode(node.get("targeting").asText()); return new Admant(uniqueId, segmentId, name, team, segmentType, teamGroups); } }
🌐
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.
🌐
Stack Overflow
stackoverflow.com › questions › 66349501 › how-to-create-a-custom-deserializer-in-jackson-for-a-list-containing-generic-typ
java - How to create a custom deserializer in Jackson for a List containing generic type? - Stack Overflow
February 24, 2021 - Copyal valueType = if (!wrapperType.isCollectionLikeType) { wrapperType.containedType(0) } else { // This is needed because there is a List that contains the WithVisibility (List<WithVisibility<String>>) wrapperType.containedType(0).containedType(0) } ... Copyinternal class WithVisibilityDeserializer : JsonDeserializer<WithVisibility<*>>(), ContextualDeserializer { private var valueType: JavaType? = null @Throws(JsonMappingException::class) override fun createContextual( ctxt: DeserializationContext, property: BeanProperty ): JsonDeserializer<*> { val wrapperType = property.type val valueType
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)
    }
}
🌐
ConcretePage
concretepage.com › jackson-api › jackson-custom-deserializer
Jackson Custom Deserializer
Jackson provides JsonDeserializer and its subclasses such as StdDeserializer to deserialize objects from JSON. We can register custom deserializer with ObjectMapper or using @JsonDeserialize annotation.
🌐
Medium
bhavinshah7.medium.com › custom-deserialization-with-jackson-a0bb5a14c04b
Custom Deserialization with Jackson | by Bhavin Shah | Medium
June 8, 2024 - Additionally, we need to handle object references introduced by Jackson during serialization to avoid infinite loops. For example, if an object references another object, which in turn references the first object, this can cause an infinite loop during serialization. While handling references is an edge case, it is crucial to address this scenario if it applies to your data structure. Let’s create a custom deserializer for TransactionRequest class, which includes a BaseEntity object and a typeInfo field to specify the type of BaseEntity.