0
# Property Naming
1
2
Dropwizard Jackson provides flexible property naming support that allows classes to use either camelCase or snake_case JSON field names based on annotations.
3
4
## AnnotationSensitivePropertyNamingStrategy
5
6
A property naming strategy that conditionally applies snake_case naming based on the presence of the `@JsonSnakeCase` annotation.
7
8
```java { .api }
9
public class AnnotationSensitivePropertyNamingStrategy extends PropertyNamingStrategy {
10
public String nameForConstructorParameter(MapperConfig<?> config,
11
AnnotatedParameter ctorParam,
12
String defaultName)
13
public String nameForField(MapperConfig<?> config,
14
AnnotatedField field,
15
String defaultName)
16
public String nameForGetterMethod(MapperConfig<?> config,
17
AnnotatedMethod method,
18
String defaultName)
19
public String nameForSetterMethod(MapperConfig<?> config,
20
AnnotatedMethod method,
21
String defaultName)
22
}
23
```
24
25
**Behavior**:
26
- **Annotated Classes**: Uses snake_case naming for classes annotated with `@JsonSnakeCase`
27
- **Default Classes**: Uses default Jackson naming (typically camelCase) for non-annotated classes
28
- **Null Safety**: Handles null parameters gracefully, returning the default name
29
30
## JsonSnakeCase Annotation
31
32
Marker annotation that indicates a class should use snake_case property names in JSON serialization.
33
34
```java { .api }
35
@Target(ElementType.TYPE)
36
@Retention(RetentionPolicy.RUNTIME)
37
@JacksonAnnotation
38
public @interface JsonSnakeCase {
39
}
40
```
41
42
**Properties**:
43
- **Target**: Can only be applied to classes/interfaces (ElementType.TYPE)
44
- **Retention**: Available at runtime for reflection
45
- **Jackson Integration**: Recognized as a Jackson annotation
46
47
## Usage Examples
48
49
### Basic Snake Case Usage
50
51
```java
52
@JsonSnakeCase
53
public class UserPreferences {
54
private String displayName;
55
private boolean enableNotifications;
56
private int maxRetryCount;
57
58
// constructors, getters, setters...
59
}
60
61
ObjectMapper mapper = Jackson.newObjectMapper();
62
UserPreferences prefs = new UserPreferences("John Doe", true, 3);
63
64
String json = mapper.writeValueAsString(prefs);
65
// Result: {"display_name":"John Doe","enable_notifications":true,"max_retry_count":3}
66
```
67
68
### Mixed Naming Strategies
69
70
```java
71
// This class uses default camelCase
72
public class StandardConfig {
73
private String serverName;
74
private int portNumber;
75
76
// constructors, getters, setters...
77
}
78
79
// This class uses snake_case
80
@JsonSnakeCase
81
public class DatabaseConfig {
82
private String connectionUrl;
83
private int maxConnections;
84
85
// constructors, getters, setters...
86
}
87
88
ObjectMapper mapper = Jackson.newObjectMapper();
89
90
StandardConfig standard = new StandardConfig("api-server", 8080);
91
DatabaseConfig database = new DatabaseConfig("jdbc:postgresql://localhost/db", 10);
92
93
String standardJson = mapper.writeValueAsString(standard);
94
// Result: {"serverName":"api-server","portNumber":8080}
95
96
String databaseJson = mapper.writeValueAsString(database);
97
// Result: {"connection_url":"jdbc:postgresql://localhost/db","max_connections":10}
98
```
99
100
### Constructor Parameter Handling
101
102
```java
103
@JsonSnakeCase
104
public class ApiKey {
105
private final String keyValue;
106
private final long createdAt;
107
108
public ApiKey(@JsonProperty("key_value") String keyValue,
109
@JsonProperty("created_at") long createdAt) {
110
this.keyValue = keyValue;
111
this.createdAt = createdAt;
112
}
113
114
// getters...
115
}
116
117
ObjectMapper mapper = Jackson.newObjectMapper();
118
119
// Both serialization and deserialization use snake_case
120
String json = "{\"key_value\":\"abc123\",\"created_at\":1640995200000}";
121
ApiKey key = mapper.readValue(json, ApiKey.class);
122
123
String serialized = mapper.writeValueAsString(key);
124
// Result: {"key_value":"abc123","created_at":1640995200000}
125
```
126
127
## Integration with ObjectMapper
128
129
The naming strategy is automatically configured when using Jackson factory methods:
130
131
```java
132
ObjectMapper mapper = Jackson.newObjectMapper();
133
// AnnotationSensitivePropertyNamingStrategy is automatically set
134
135
ObjectMapper minimal = Jackson.newMinimalObjectMapper();
136
// Does NOT include the custom naming strategy (uses default)
137
```
138
139
## Compatibility
140
141
The naming strategy works with:
142
- **Field-based** serialization/deserialization
143
- **Getter/Setter** method-based serialization/deserialization
144
- **Constructor parameter** deserialization with preserved parameter names
145
- **Mixed approaches** within the same application
146
147
**Note**: The strategy only affects classes directly annotated with `@JsonSnakeCase`. Nested objects follow their own annotation rules.