When is the @JsonProperty property used and what is it used for?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
@JsonProperty is a Jackson annotation that controls how Java fields map to JSON property names during serialization and deserialization. You use it when the default name-based mapping is insufficient: to rename fields, to bind constructor parameters for immutable objects, to restrict access direction, or to mark a field as required. Without it, Jackson relies on field names and JavaBean conventions, which often do not match external API contracts.
Renaming Fields Between Java and JSON
The most common use case is bridging naming conventions. Java uses camelCase; many REST APIs use snake_case. @JsonProperty lets you keep Java conventions in your code while matching the external contract exactly.
Serialization output:
Without the annotation, Jackson would emit firstName, lastName, and createdAt, which might break client integrations that expect snake_case.
Global naming strategy vs per-field annotation
If every field in your API follows snake_case, configuring the ObjectMapper globally is cleaner than annotating every field:
Use @JsonProperty when only specific fields deviate from the default, or when you need a name that no naming strategy can generate automatically (like mapping type to __type or class to _class).
Constructor Binding for Immutable Objects
When a class has final fields and no default constructor, Jackson needs explicit guidance on how to bind JSON keys to constructor parameters. @JsonProperty on constructor arguments provides that mapping.
Without @JsonProperty on the constructor parameters, Jackson cannot reliably match JSON fields to arguments, especially when compiled without the -parameters flag. The deserialization either fails or produces incorrect bindings.
This pattern is especially important with Java records, where all fields are final by design:
Controlling Serialization Direction With Access
@JsonProperty supports an access attribute that controls whether a field participates in reading (deserialization), writing (serialization), or both.
| Access mode | Serialization (Java to JSON) | Deserialization (JSON to Java) |
READ_WRITE (default) | Included | Accepted |
WRITE_ONLY | Excluded | Accepted |
READ_ONLY | Included | Ignored |
WRITE_ONLY is common for password fields in request DTOs. The field is accepted from incoming JSON but never appears in outgoing responses. READ_ONLY is useful for server-generated values like IDs, timestamps, or computed fields that should be serialized out but should not be overwritten by client input.
Marking Fields as Required
The required attribute on @JsonProperty signals that the field must be present during deserialization. When combined with @JsonCreator, Jackson throws a MismatchedInputException if the required field is missing from the JSON input.
This is a lightweight validation mechanism. For more complex validation rules (length constraints, pattern matching), combine with Bean Validation annotations like @NotNull or @Size.
Annotation Placement Options
You can place @JsonProperty on fields, getters, setters, or constructor parameters. The best location depends on your class design:
| Placement | Best for | Example |
| Field | Simple DTOs with direct field access | @JsonProperty("user_id") private Long userId; |
| Constructor parameter | Immutable objects, records | @JsonCreator public Foo(@JsonProperty("bar") String bar) |
| Getter | Method-based serialization logic | @JsonProperty("full_name") public String getFullName() |
| Setter | Custom deserialization with validation | @JsonProperty("age") public void setAge(int age) |
Consistency matters. If your team annotates fields in some DTOs and getters in others, the mapping becomes harder to audit. Pick one style per project and document it.
Combining With Other Jackson Annotations
@JsonProperty often works alongside other annotations:
@JsonIgnore excludes a field entirely. @JsonInclude controls when a field appears based on its value. @JsonRawValue writes a string as raw JSON rather than escaping it. These annotations complement @JsonProperty rather than replacing it.
When You Do Not Need @JsonProperty
You do not need the annotation when:
- Field names already match the JSON contract exactly.
- A global naming strategy handles the transformation (e.g.,
SNAKE_CASE). - The class has a default constructor and standard getters/setters that Jackson can discover through reflection.
Adding @JsonProperty("username") to a field already named username adds noise without adding clarity. Reserve the annotation for cases where it changes behavior.
Common Pitfalls
Annotating every field even when default mapping already works. This clutters the code and makes real overrides harder to spot. Only annotate when the external name differs from the Java name or when you need constructor binding.
Forgetting constructor parameter annotations on immutable types. Serialization (Java to JSON) often works fine because Jackson reads fields directly. Deserialization (JSON to Java) fails because Jackson cannot map JSON keys to unnamed constructor parameters.
Confusing WRITE_ONLY with security. The access attribute prevents serialization of a field, but it does not replace proper secret handling, hashing, or encryption. A password field marked WRITE_ONLY still exists in memory and can appear in logs or debug output.
Mixing field and method annotations for the same property. Jackson can handle it, but the behavior depends on visibility settings and can produce surprising results. Annotate in one place per property.
Using @JsonProperty when @JsonNaming would be simpler. If every field in a class needs snake_case mapping, applying a class-level @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) is more maintainable than annotating every field individually.
Summary
@JsonPropertycustomizes the mapping between a Java property and a JSON field name. Use it when names differ across conventions.- On constructor parameters, it enables deserialization of immutable objects and records.
- The
accessattribute controls serialization direction:WRITE_ONLYfor input-only fields,READ_ONLYfor output-only fields. - The
requiredattribute enforces presence during deserialization. - Prefer a global naming strategy when the entire API follows a single convention. Use
@JsonPropertyfor individual overrides. - Do not annotate fields whose names already match the JSON contract. Unnecessary annotations add noise.

