278

This bean 'State' :

public class State {

    private boolean isSet;

    @JsonProperty("isSet")
    public boolean isSet() {
        return isSet;
    }

    @JsonProperty("isSet")
    public void setSet(boolean isSet) {
        this.isSet = isSet;
    }

}

is sent over the wire using the ajax ' success' callback :

        success : function(response) {  
            if(response.State.isSet){   
                alert('success called successfully)
            }

Is the annotation @JsonProperty required here ? What is the advantage of using it ? I think I can remove this annotation without causing any side effects.

Reading about this annotion on https://github.com/FasterXML/jackson-annotations/wiki/Jackson-Annotations I don't know when this is required to be used ?

Carsten
  • 361
  • 3
  • 14
blue-sky
  • 51,962
  • 152
  • 427
  • 752

9 Answers9

335

Here's a good example. I use it to rename the variable because the JSON is coming from a .Net environment where properties start with an upper-case letter.

public class Parameter {
  @JsonProperty("Name")
  public String name;
  @JsonProperty("Value")
  public String value; 
}

This correctly parses to/from the JSON:

"Parameter":{
  "Name":"Parameter-Name",
  "Value":"Parameter-Value"
}
OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213
  • 1
    Can the the String member variables not be renamed to their correct case, so public String name; becomes public String Name; ? – blue-sky Sep 25 '12 at 13:29
  • 23
    Yes they can, but in a Java environment that makes them not match coding standards. It's more about my pedantry that a real coding issue but it is a good yet simple example of a real use of the `@JsonProperty` annotation. – OldCurmudgeon Sep 25 '12 at 14:43
  • Can this annotation be used for the member of type `Double`? I'm just wondering if the type has to be `String` or any type that JSON support? Could it be any type?@OldCurmudgeon – Dreamer Jul 25 '17 at 02:04
  • 4
    @Dreamer Yes. The type is irrelevant. This only affects the **name**. – OldCurmudgeon Jul 25 '17 at 05:39
  • @OldCurmudgeon This is not working for me. In response, I can see the names got changed to lowercase but all the values all are null. In the json, all those fields have values. – Pavan Aug 02 '17 at 11:13
  • 1
    @Pavan - That won't have anything to do with the naming. I'd **guess** you should examine your setters. – OldCurmudgeon Aug 02 '17 at 12:18
  • @OldCurmudgeon can you please give me the sample code. – Pavan Aug 02 '17 at 12:22
  • I am wondering if there is any documentation about how to actually use these annotations? I have looked on the github repo as well as java docs with 0 results for examples or explanations on how they work. https://github.com/FasterXML/jackson-annotations/wiki/Jackson-Annotations http://fasterxml.github.io/jackson-annotations/javadoc/2.10/ – Russell Lego Nov 05 '19 at 22:14
  • Here you can find usage examples: https://www.baeldung.com/jackson-annotations – Catalin Pirvu Apr 06 '21 at 07:35
62

I think OldCurmudgeon and StaxMan are both correct but here is one sentence answer with simple example for you.

@JsonProperty(name), tells Jackson ObjectMapper to map the JSON property name to the annotated Java field's name.

//example of json that is submitted 
"Car":{
  "Type":"Ferrari",
}

//where it gets mapped 
public static class Car {
  @JsonProperty("Type")
  public String type;
 }
grepit
  • 21,260
  • 6
  • 105
  • 81
  • Does the Class name should be same as the root element of JSON. This is not working for me. – Pavan Aug 02 '17 at 11:15
49

well for what its worth now... JsonProperty is ALSO used to specify getter and setter methods for the variable apart from usual serialization and deserialization. For example suppose you have a payload like this:

{
  "check": true
}

and a Deserializer class:

public class Check {

  @JsonProperty("check")    // It is needed else Jackson will look got getCheck method and will fail
  private Boolean check;

  public Boolean isCheck() {
     return check;
  }
}

Then in this case JsonProperty annotation is neeeded. However if you also have a method in the class

public class Check {

  //@JsonProperty("check")    Not needed anymore
  private Boolean check;

  public Boolean getCheck() {
     return check;
  }
}

Have a look at this documentation too: http://fasterxml.github.io/jackson-annotations/javadoc/2.13/com/fasterxml/jackson/annotation/JsonProperty.html

g t
  • 7,287
  • 7
  • 50
  • 85
Richeek
  • 2,068
  • 2
  • 29
  • 37
30

Without annotations, inferred property name (to match from JSON) would be "set", and not -- as seems to be the intent -- "isSet". This is because as per Java Beans specification, methods of form "isXxx" and "setXxx" are taken to mean that there is logical property "xxx" to manage.

StaxMan
  • 113,358
  • 34
  • 211
  • 239
12

As you know, this is all about serialize and desalinize an object. Suppose there is an object:

public class Parameter {
  public String _name;
  public String _value; 
}

The serialization of this object is:

{
  "_name": "...",
  "_value": "..."
}

The name of variable is directly used to serialize data. If you are about to remove system api from system implementation, in some cases, you have to rename variable in serialization/deserialization. @JsonProperty is a meta data to tell serializer how to serial object. It is used to:

  • variable name
  • access (READ, WRITE)
  • default value
  • required/optional

from example:

public class Parameter {
  @JsonProperty(
        value="Name",
        required=true,
        defaultValue="No name",
        access= Access.READ_WRITE)
  public String _name;
  @JsonProperty(
        value="Value",
        required=true,
        defaultValue="Empty",
        access= Access.READ_WRITE)
  public String _value; 
}
Mostafa Barmshory
  • 1,849
  • 24
  • 39
11

Adding the JsonProperty also ensures safety in case someone decides they want to change one of the property names not realizing the class in question will be serialized to a Json object. If they change the property name the JsonProperty ensures it will be used in the Json object, and not the property name.

arush436
  • 1,748
  • 20
  • 20
10

In addition to all the answers above, don't forget the part of the documentation that says

Marker annotation that can be used to define a non-static method as a "setter" or "getter" for a logical property (depending on its signature), or non-static object field to be used (serialized, deserialized) as a logical property.

If you have a non-static method in your class that is not a conventional getter or setter then you can make it act like a getter and setter by using the annotation on it. See the example below

public class Testing {
    private Integer id;
    private String username;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getIdAndUsername() {
        return id + "." + username; 
    }

    public String concatenateIdAndUsername() {
        return id + "." + username; 
    }
}

When the above object is serialized, then response will contain

  • username from getUsername()
  • id from getId()
  • idAndUsername from getIdAndUsername*

Since the method getIdAndUsername starts with get then it's treated as normal getter hence, why you could annotate such with @JsonIgnore.

If you have noticed the concatenateIdAndUsername is not returned and that's because it name does not start with get and if you wish the result of that method to be included in the response then you can use @JsonProperty("...") and it would be treated as normal getter/setter as mentioned in the above highlighted documentation.

Raf
  • 7,505
  • 1
  • 42
  • 59
7

As addition to other answers, @JsonProperty annotation is really important if you use the @JsonCreator annotation in classes which do not have a no-arg constructor.

public class ClassToSerialize {

    public enum MyEnum {
        FIRST,SECOND,THIRD
    }

    public String stringValue = "ABCD";
    public MyEnum myEnum;


    @JsonCreator
    public ClassToSerialize(MyEnum myEnum) {
        this.myEnum = myEnum;
    }

    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();

        ClassToSerialize classToSerialize = new ClassToSerialize(MyEnum.FIRST);
        String jsonString = mapper.writeValueAsString(classToSerialize);
        System.out.println(jsonString);
        ClassToSerialize deserialized = mapper.readValue(jsonString, ClassToSerialize.class);
        System.out.println("StringValue: " + deserialized.stringValue);
        System.out.println("MyEnum: " + deserialized.myEnum);
    }
}

In this example the only constructor is marked as @JsonCreator, therefore Jackson will use this constructor to create the instance. But the output is like:

Serialized: {"stringValue":"ABCD","myEnum":"FIRST"}

Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not construct instance of ClassToSerialize$MyEnum from String value 'stringValue': value not one of declared Enum instance names: [FIRST, SECOND, THIRD]

But after the addition of the @JsonProperty annotation in the constructor:

@JsonCreator
public ClassToSerialize(@JsonProperty("myEnum") MyEnum myEnum) {
    this.myEnum = myEnum;
}

The deserialization is successful:

Serialized: {"myEnum":"FIRST","stringValue":"ABCD"}

StringValue: ABCD

MyEnum: FIRST

DVarga
  • 21,311
  • 6
  • 55
  • 60
1

From JsonProperty javadoc,

Defines name of the logical property, i.e. JSON object field name to use for the property. If value is empty String (which is the default), will try to use name of the field that is annotated.

sc30
  • 131
  • 1
  • 8