Method hasIgnoreMarker is called not only for fields, but also for the constructor, including the virtual one:

Method called to check whether given property is marked to be ignored. This is used to determine whether to ignore properties, on per-property basis, usually combining annotations from multiple accessors (getters, setters, fields, constructor parameters).

In this case you should ignore only fields, that are not marked properly:

static class CustomAnnotationIntrospector extends JacksonAnnotationIntrospector {
    @Override
    public PropertyName findNameForDeserialization(Annotated a) {
        Property property = a.getAnnotation(Property.class);
        if (property == null) {
            return PropertyName.USE_DEFAULT;
        } else {
            return PropertyName.construct(property.name());
        }
    }

    @Override
    public boolean hasIgnoreMarker(AnnotatedMember m) {
        return m instanceof AnnotatedField
                && m.getAnnotation(Property.class) == null;
    }
}

Example:

class Pojo {
//    @Property(name = "id")
    Integer id;
//    @Property(name = "number")
    Integer number;
    @Property(name = "assure")
    Boolean assure;
    @Property(name = "person")
    Map<String, String> person;
}
String json =
        "{\"id\" : 1, \"number\" : 12345, \"assure\" : true," +
        " \"person\" : {\"name\" : \"John\", \"age\" : 23}}";

ObjectMapper mapper = new ObjectMapper();
mapper.setAnnotationIntrospector(new CustomAnnotationIntrospector());
Pojo pojo = mapper.readValue(json, Pojo.class);

System.out.println(pojo);
Pojo{id=null, number=null, assure=true, person={name=John, age=23}}

Note: Custom Property annotation should have RetentionPolicy.RUNTIME (same as JsonProperty annotation):

@Retention(RetentionPolicy.RUNTIME)
public @interface Property {
    String name();
}
Answer from user11141611 on Stack Overflow
🌐
TutorialsPoint
tutorialspoint.com › jackson_annotations › jackson_annotations_jsondeserialize.htm
Jackson Annotations - @JsonDeserialize
@JsonDeserialize annotation is used to specify custom deserializer to unmarshall the json object. package com.tutorialspoint; import java.io.IOException; import java.text.ParseException; import java.util.Date; import com.fasterxml.jackson.d...
🌐
DZone
dzone.com › coding › languages › jackson annotations for json (part 3): deserialization
Jackson Annotations for JSON (Part 3): Deserialization - DZone
December 25, 2017 - The @JacksonInject annotation is used to tell Jackson that particular values of the deserialized object will be injected and not read from the JSON string. An example of Java class where the personId field is injected by Jackson is:
🌐
Medium
medium.com › @bubu.tripathy › json-serialization-and-deserialization-in-java-2a3f08266b70
JSON Serialization and Deserialization in Java | by Bubu Tripathy | Medium
April 9, 2023 - The FasterXML Jackson library is a popular Java library used for working with JSON data. It provides a number of annotations that can be used to customize the serialization and deserialization of JSON data.
Top answer
1 of 2
3

Method hasIgnoreMarker is called not only for fields, but also for the constructor, including the virtual one:

Method called to check whether given property is marked to be ignored. This is used to determine whether to ignore properties, on per-property basis, usually combining annotations from multiple accessors (getters, setters, fields, constructor parameters).

In this case you should ignore only fields, that are not marked properly:

static class CustomAnnotationIntrospector extends JacksonAnnotationIntrospector {
    @Override
    public PropertyName findNameForDeserialization(Annotated a) {
        Property property = a.getAnnotation(Property.class);
        if (property == null) {
            return PropertyName.USE_DEFAULT;
        } else {
            return PropertyName.construct(property.name());
        }
    }

    @Override
    public boolean hasIgnoreMarker(AnnotatedMember m) {
        return m instanceof AnnotatedField
                && m.getAnnotation(Property.class) == null;
    }
}

Example:

class Pojo {
//    @Property(name = "id")
    Integer id;
//    @Property(name = "number")
    Integer number;
    @Property(name = "assure")
    Boolean assure;
    @Property(name = "person")
    Map<String, String> person;
}
String json =
        "{\"id\" : 1, \"number\" : 12345, \"assure\" : true," +
        " \"person\" : {\"name\" : \"John\", \"age\" : 23}}";

ObjectMapper mapper = new ObjectMapper();
mapper.setAnnotationIntrospector(new CustomAnnotationIntrospector());
Pojo pojo = mapper.readValue(json, Pojo.class);

System.out.println(pojo);
Pojo{id=null, number=null, assure=true, person={name=John, age=23}}

Note: Custom Property annotation should have RetentionPolicy.RUNTIME (same as JsonProperty annotation):

@Retention(RetentionPolicy.RUNTIME)
public @interface Property {
    String name();
}
2 of 2
0

I will suggest a different approach:

In the runtime, with the bytecode instrumentation library Byte Buddy and its Java agent, re-annotate the fields with the proper Jackson Annotations. Simply implement the logic via reflection. See the following example:

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.description.annotation.AnnotationDescription;
import net.bytebuddy.dynamic.DynamicType.Builder;
import net.bytebuddy.dynamic.DynamicType.Builder.FieldDefinition.Valuable;
import net.bytebuddy.dynamic.loading.ClassReloadingStrategy;
import net.bytebuddy.matcher.ElementMatchers;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyJsonIgnore {
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyJsonProperty {
  String name();
}
public class Sample {
  public static void main(String[] args) throws JsonProcessingException {
    ByteBuddyAgent.install();
    ClassReloadingStrategy classReloadingStrategy = ClassReloadingStrategy.fromInstalledAgent();
    ByteBuddy byteBuddy = new ByteBuddy();
    AnnotationDescription jsonIgnoreDesc =
        AnnotationDescription.Builder.ofType(JsonIgnore.class).build();

    Builder<Person> personBuilder = byteBuddy.redefine(Person.class);

    for (Field declaredField : Person.class.getDeclaredFields()) {
      Valuable<Person> field = personBuilder.field(ElementMatchers.named(declaredField.getName()));

      MyJsonProperty myJsonProperty = declaredField.getAnnotation(MyJsonProperty.class);
      if (myJsonProperty != null) {
        AnnotationDescription jsonPropertyDesc =
            AnnotationDescription.Builder.ofType(JsonProperty.class)
                .define("value", myJsonProperty.name())
                .build();
        personBuilder = field.annotateField(jsonPropertyDesc);
      }

      MyJsonIgnore myJsonIgnore = declaredField.getAnnotation(MyJsonIgnore.class);
      if (myJsonIgnore != null) {
        personBuilder = field.annotateField(jsonIgnoreDesc);
      }
    }

    personBuilder.make().load(Sample.class.getClassLoader(), classReloadingStrategy);

    Person person = new Person("Utku", "Ozdemir", "Berlin");
    
    ObjectMapper objectMapper = new ObjectMapper();
    String jsonString = objectMapper.writeValueAsString(person);
    System.out.println(jsonString);
  }
}
class Person {
  @MyJsonProperty(name = "FIRST")
  private String firstName;

  @MyJsonProperty(name = "LAST")
  private String lastName;

  @MyJsonIgnore private String city;

  public Person(String firstName, String lastName, String city) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.city = city;
  }
}

In the example above, I

  • create MyJsonProperty and MyJsonIgnore annotations and a Person class for the demonstration purpose
  • instrument the current Java process with the Byte buddy agent
  • create a bytebuddy builder to redefine the Person class
  • loop over the fields of the Person class and check for these annotations
  • add an additional annotation to each of those fields (on the builder), Jackson's JsonProperty (with the correct field name mapping) and JsonIgnore.
  • after being done with the fields, make the new class bytecode and load it to the current classloader using the byte buddy agent's class reloading mechanism
  • write a person object to the stdout.

It prints, as expected:

{"FIRST":"Utku","LAST":"Ozdemir"}

(the field city is ignored)

This solution might feel like an overkill, but on the other side, it is pretty generic solution - with a few changes in the logic, you could handle all the 3rd party classes (which you are not able to modify) instead of handling them case by case.

🌐
Stack Overflow
stackoverflow.com › questions › 56084210 › deserialize-strings-and-objects-using-jackson-annotations-in-java
json - Deserialize strings and objects using jackson annotations in java - Stack Overflow
May 11, 2019 - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.File; import java.util.List; import java.util.Map; public class JsonApp { public static void main(String[] args) throws Exception { File jsonFile = new File("./resource/test.json").getAbsoluteFile(); ObjectMapper mapper = new ObjectMapper(); System.out.println(mapper.readValue(jsonFile, DeserializationClass.class)); } } class DeserializationClass { Map<String, List<AnotherClass>> nodes; @JsonCreator DeserializationClass(@J
🌐
Javadoc.io
javadoc.io › doc › com.fasterxml.jackson.core › jackson-databind › latest › com › fasterxml › jackson › databind › annotation › JsonDeserialize.html
JsonDeserialize - jackson-databind 2.22.1 javadoc
Bookmarks · Latest version of com.fasterxml.jackson.core:jackson-databind · https://javadoc.io/doc/com.fasterxml.jackson.core/jackson-databind · Current version 2.22.1 · https://javadoc.io/doc/com.fasterxml.jackson.core/jackson-databind/2.22.1 · package-list path (used for javadoc generation ...
Find elsewhere
🌐
TutorialsPoint
tutorialspoint.com › article › how-to-implement-custom-deserializer-using-jsondeserialize-annotation-in-java
How to implement custom deserializer using @JsonDeserialize annotation in Java?
July 9, 2020 - The @JsonDeserialize annotation is used to declare custom deserializer while deserializing JSON to Java object. We can implement a custom deserializer by extending the StdDeserializer class with a generic type Employee and need to override the
Top answer
1 of 3
2

You can try to implement custom deserialiser with com.fasterxml.jackson.databind.deser.ContextualDeserializer interface. It allows to create deserialiser instance with a context.

See below example:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.json.JsonMapper;
import lombok.Data;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

public class JsonContextualDeserializerApp {
    public static void main(String[] args) throws IOException {
        File jsonFile = new File("./resource/test.json").getAbsoluteFile();

        ObjectMapper mapper = JsonMapper.builder().build();
        RelationsInput info = mapper.readValue(jsonFile, RelationsInput.class);

        System.out.println(info.toString());
    }
}

@Data
class RelationsInput {

    @JsonDeserialize(using = RelationStdDeserializer.class)
    @RelationTypeInfo(RelationType.OWNER)
    private Relation owner;

    @JsonDeserialize(using = RelationStdDeserializer.class)
    @RelationTypeInfo(RelationType.TENANT)
    private Relation tenant;

}

@Data
class Relation {

    private int id;
    private RelationType relationtype;
}

enum RelationType {OWNER, TENANT}

@Retention(RetentionPolicy.RUNTIME)
@interface RelationTypeInfo {
    RelationType value();
}

class RelationStdDeserializer extends StdDeserializer<Relation> implements ContextualDeserializer {

    private RelationType propertyRelationType;

    public RelationStdDeserializer() {
        this(null);
    }

    public RelationStdDeserializer(RelationType relationType) {
        super(Relation.class);
        this.propertyRelationType = relationType;
    }

    @Override
    public Relation deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        JsonDeserializer<Object> deser = ctxt.findRootValueDeserializer(ctxt.getTypeFactory().constructType(Relation.class));
        Relation instance = (Relation) deser.deserialize(p, ctxt);
        if (this.propertyRelationType != null) {
            instance.setRelationtype(this.propertyRelationType);
        }
        return instance;
    }

    @Override
    public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) {
        RelationTypeInfo typeInfo = property.getMember().getAllAnnotations().get(RelationTypeInfo.class);

        return new RelationStdDeserializer(typeInfo.value());
    }
}

Above code for a payload:

{
  "owner": {
    "id": 1
  },
  "tenant": {
    "id": 2
  }
}

prints:

RelationsInput(owner=Relation(id=1, relationtype=OWNER), tenant=Relation(id=2, relationtype=TENANT))

See also:

  • Deserialize to String or Object using Jackson
  • How to inject dependency into Jackson Custom deserializer
  • Jackson - deserialize inner list of objects to list of one higher level
2 of 3
0

I am afraid there is not such thing. If you want to use something annotation like you could use custom de-serializers. Create first something like:

@RequiredArgsConstructor
public abstract class RelationTypeDeserializer extends JsonDeserializer<Relation> {
    private final RelationType relationType;

    @Override
    public Relation deserialize(JsonParser p, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        Relation r = p.readValueAs(Relation.class);
        r.setRelationtype(relationType);
        return r;
    }
}

Then implement the actual ones:

public class OwnerDeserializer extends RelationTypeDeserializer {
    public OwnerDeserializer() {
        super(RelationType.OWNER);
    }   
}

and

public class TenantDeserializer extends RelationTypeDeserializer {
    public TenantDeserializer() {
        super(RelationType.TENANT);
    }
}

then use those like:

@Getter @Setter
public class RelationsInput {
    @JsonDeserialize(using = OwnerDeserializer.class)
    private Relation owner;
    @JsonDeserialize(using = TenantDeserializer.class)
    private Relation tenant;
}
🌐
Baeldung
baeldung.com › home › json › jackson › forcing jackson to deserialize to specific type
Forcing Jackson to Deserialize to Specific Type | Baeldung
October 15, 2025 - We explored different methods to achieve this, such as using a custom deserializer, configuring the ObjectMapper to use a deserialization feature, and using the @JsonTypeInfo annotation to specify the type information for the value field.
🌐
Java Guides
javaguides.net › 2023 › 10 › java-jackson-jsondeserialize.html
Java Jackson @JsonDeserialize
October 26, 2023 - The @JsonDeserialize annotation is employed in Jackson to specify custom deserialization for Java objects.
🌐
Baeldung
baeldung.com › home › json › jackson › jackson annotation examples
Jackson Annotation Examples | Baeldung
April 14, 2023 - We can add the @JsonProperty annotation to indicate the property name in JSON. Let’s use @JsonProperty to serialize/deserialize the property name when we’re dealing with non-standard getters and setters:
🌐
Jenkov
jenkov.com › tutorials › java-json › jackson-annotations.html
Jackson Annotations
November 18, 2015 - The Jackson annotation @JsonDeserialize is used to specify a custom de-serializer class for a given field in a Java object. For instance, imagine you wanted to optimize the on-the-wire formatting of the boolean values false and true to 0 and ...
🌐
Reflectoring
reflectoring.io › jackson-jsonview-tutorial
Serialize and Deserialize with Jackson's @JsonView in a Spring Boot Application
April 26, 2023 - Step 2: Use the class or interface with @JsonView annotations in models or DTOs · Step 3: Annotate the controller class methods or @RequestBody params with the view to be used for serializing or deserializing the object.
🌐
CodeMiner42
blog.codeminer42.com › home › posts › serialization and deserialization in java using jackson
Serialization and Deserialization in Java using Jackson - The Miners
May 29, 2023 - The @JsonProperty annotation is used for mapping an attribute with a JSON key name in both serialization and deserialization. By default when we serialize an object, Jackson will map JSON keys matching the name of the object’s attributes.
🌐
Stack Abuse
stackabuse.com › definitive-guide-to-jackson-objectmapper-serialize-and-deserialize-java-objects
Definitive Guide to Jackson ObjectMapper - Serialize and Deserialize Java Objects
October 27, 2023 - To avoid this more "global" configuration, we can add this annotation at a class level: @JsonIgnoreProperties(ignoreUnknown = true). The FAIL_ON_NULL_FOR_PRIMITIVES feature determines whether to fail when encountering JSON properties as null while deserializing into Java primitive types (like int or double).
🌐
Spring Framework Guru
springframework.guru › home › mastering jackson annotations: a guide to simplified json mapping for java
Mastering Jackson Annotations: A Guide to Simplified JSON Mapping for Java -
October 22, 2024 - The @JsonIgnore annotation marks a field in a POJO to be ignored by Jackson during serialization and deserialization. Jackson ignores the field in both JSON serialization and deserialization.
Top answer
1 of 2
1

You can write a custom deserializer:

public static class XyzDeserializer extends JsonDeserializer<Map<Integer, String>> {

    @Override
    public Map<Integer, String> deserialize(JsonParser p,
                                            DeserializationContext ctxt) throws IOException {
        JsonNode rootNode = p.getCodec().readTree(p);
        Map<Integer, String> map = new HashMap<>();
        rootNode.forEach(n -> map.put(
                n.get("fooId").intValue(),
                n.get("barVal").asText()
        ));
        return map;
    }
}

And use it in this way:

@JsonCreator
public FooBar(
        @JsonProperty("blargs")
        @JsonDeserialize(using = XyzDeserializer.class) Map<Integer, String> xyz) {
    this.xyz = xyz;
}
2 of 2
1

You need a class for the data

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.List;

public class JsonApp {

    public static void main(String[] args) throws IOException {
        String json = "{\"blargs\":[\n"
                + "    {\"fooId\":888,\"barVal\":\"tacos\"},\n"
                + "    {\"fooId\":222,\"barVal\":\"hamburgers\"},\n"
                + "    {\"fooId\":444,\"barVal\":\"underpants\"}\n"
                + "  ]\n"
                + "}";
        ObjectMapper mapper = new ObjectMapper();
        FooBar fooBar = mapper.readValue(json, FooBar.class);
    }

    public static class FooBar {

        private List<MyObject> xyz;

        @JsonCreator
        public FooBar(@JsonProperty("blargs") List<MyObject> xyz) {
            this.xyz = xyz;
            System.out.println(this.xyz);
        }

    }

    public static class MyObject {

        private int fooId;
        private String barVal;

        public int getFooId() {
            return fooId;
        }

        public void setFooId(int fooId) {
            this.fooId = fooId;
        }

        public String getBarVal() {
            return barVal;
        }

        public void setBarVal(String barVal) {
            this.barVal = barVal;
        }

        @Override
        public String toString() {
            return "MyObject{" + "fooId=" + fooId + ", barVal=" + barVal + '}';
        }

    }
}