0
# JSON Serialization Support
1
2
Jackson JSON serialization support for Spring Security LDAP classes enabling serialization and deserialization of LDAP user details and authorities.
3
4
## Capabilities
5
6
### LdapJackson2Module
7
8
Jackson module providing serialization support for Spring Security LDAP classes.
9
10
```java { .api }
11
/**
12
* Jackson module that provides serialization support for Spring Security LDAP classes
13
*/
14
public class LdapJackson2Module extends SimpleModule {
15
/**
16
* Creates the LDAP Jackson module with default configuration
17
*/
18
public LdapJackson2Module();
19
20
/**
21
* Sets up the module with mixins for LDAP classes
22
* @param context the setup context
23
*/
24
@Override
25
public void setupModule(SetupContext context);
26
}
27
```
28
29
### Jackson Mixins
30
31
Mixin classes providing JSON serialization configuration for LDAP objects.
32
33
```java { .api }
34
/**
35
* Jackson mixin for LdapUserDetailsImpl serialization
36
*/
37
public abstract class LdapUserDetailsImplMixin {
38
@JsonCreator
39
LdapUserDetailsImplMixin(@JsonProperty("dn") String dn,
40
@JsonProperty("username") String username,
41
@JsonProperty("password") String password,
42
@JsonProperty("enabled") boolean enabled,
43
@JsonProperty("accountNonExpired") boolean accountNonExpired,
44
@JsonProperty("credentialsNonExpired") boolean credentialsNonExpired,
45
@JsonProperty("accountNonLocked") boolean accountNonLocked,
46
@JsonProperty("authorities") Collection<? extends GrantedAuthority> authorities);
47
48
@JsonIgnore
49
abstract Attributes getAttributes();
50
}
51
52
/**
53
* Jackson mixin for Person serialization
54
*/
55
public abstract class PersonMixin {
56
@JsonCreator
57
PersonMixin(@JsonProperty("dn") String dn,
58
@JsonProperty("cn") String cn,
59
@JsonProperty("sn") String sn);
60
61
@JsonProperty
62
abstract String getCn();
63
64
@JsonProperty
65
abstract String getSn();
66
67
@JsonProperty
68
abstract String getDescription();
69
70
@JsonProperty
71
abstract String getTelephoneNumber();
72
}
73
74
/**
75
* Jackson mixin for InetOrgPerson serialization
76
*/
77
public abstract class InetOrgPersonMixin extends PersonMixin {
78
@JsonCreator
79
InetOrgPersonMixin(@JsonProperty("dn") String dn,
80
@JsonProperty("cn") String cn,
81
@JsonProperty("sn") String sn);
82
83
@JsonProperty
84
abstract String getMail();
85
86
@JsonProperty
87
abstract String getEmployeeNumber();
88
89
@JsonProperty
90
abstract String getDisplayName();
91
92
@JsonProperty
93
abstract String getDepartmentNumber();
94
95
@JsonProperty
96
abstract String getCarLicense();
97
98
@JsonProperty
99
abstract String getHomePhone();
100
}
101
102
/**
103
* Jackson mixin for LdapAuthority serialization
104
*/
105
public abstract class LdapAuthorityMixin {
106
@JsonCreator
107
LdapAuthorityMixin(@JsonProperty("role") String role,
108
@JsonProperty("dn") String dn);
109
110
@JsonProperty
111
abstract String getAuthority();
112
113
@JsonProperty
114
abstract String getDn();
115
}
116
```
117
118
## Usage Examples
119
120
### Basic Module Registration
121
122
```java
123
@Configuration
124
public class JacksonConfig {
125
126
@Bean
127
@Primary
128
public ObjectMapper objectMapper() {
129
ObjectMapper mapper = new ObjectMapper();
130
mapper.registerModule(new LdapJackson2Module());
131
return mapper;
132
}
133
}
134
```
135
136
### Serialization Example
137
138
```java
139
@Service
140
public class LdapUserSerializationService {
141
142
private final ObjectMapper objectMapper;
143
144
public LdapUserSerializationService(ObjectMapper objectMapper) {
145
this.objectMapper = objectMapper;
146
}
147
148
public String serializeUser(LdapUserDetails user) throws JsonProcessingException {
149
return objectMapper.writeValueAsString(user);
150
}
151
152
public LdapUserDetails deserializeUser(String json) throws JsonProcessingException {
153
return objectMapper.readValue(json, LdapUserDetailsImpl.class);
154
}
155
156
public String serializePerson(Person person) throws JsonProcessingException {
157
return objectMapper.writeValueAsString(person);
158
}
159
160
public Person deserializePerson(String json) throws JsonProcessingException {
161
return objectMapper.readValue(json, Person.class);
162
}
163
}
164
```
165
166
### Spring Boot Auto-Configuration
167
168
```java
169
@Configuration
170
@ConditionalOnClass({ObjectMapper.class, LdapUserDetails.class})
171
public class LdapJacksonAutoConfiguration {
172
173
@Bean
174
@ConditionalOnMissingBean
175
public LdapJackson2Module ldapJackson2Module() {
176
return new LdapJackson2Module();
177
}
178
179
@Bean
180
@Primary
181
public ObjectMapper ldapObjectMapper(LdapJackson2Module ldapModule) {
182
return JsonMapper.builder()
183
.addModule(ldapModule)
184
.build();
185
}
186
}
187
```
188
189
### Custom Serialization Configuration
190
191
```java
192
@Configuration
193
public class CustomLdapSerializationConfig {
194
195
@Bean
196
public ObjectMapper customLdapMapper() {
197
ObjectMapper mapper = new ObjectMapper();
198
199
// Register LDAP module
200
mapper.registerModule(new LdapJackson2Module());
201
202
// Custom configuration
203
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
204
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
205
206
// Custom mixins for additional classes
207
mapper.addMixIn(CustomLdapUser.class, CustomLdapUserMixin.class);
208
209
return mapper;
210
}
211
}
212
213
// Example custom mixin
214
abstract class CustomLdapUserMixin {
215
@JsonCreator
216
CustomLdapUserMixin(@JsonProperty("username") String username,
217
@JsonProperty("department") String department,
218
@JsonProperty("manager") String manager);
219
220
@JsonProperty("dept")
221
abstract String getDepartment();
222
223
@JsonIgnore
224
abstract String getInternalId();
225
}
226
```
227
228
### REST Controller Integration
229
230
```java
231
@RestController
232
@RequestMapping("/api/ldap")
233
public class LdapUserController {
234
235
private final LdapUserDetailsService userDetailsService;
236
private final ObjectMapper objectMapper;
237
238
public LdapUserController(LdapUserDetailsService userDetailsService,
239
ObjectMapper objectMapper) {
240
this.userDetailsService = userDetailsService;
241
this.objectMapper = objectMapper;
242
}
243
244
@GetMapping("/users/{username}")
245
public ResponseEntity<String> getUser(@PathVariable String username) {
246
try {
247
UserDetails user = userDetailsService.loadUserByUsername(username);
248
String json = objectMapper.writeValueAsString(user);
249
return ResponseEntity.ok(json);
250
} catch (UsernameNotFoundException e) {
251
return ResponseEntity.notFound().build();
252
} catch (JsonProcessingException e) {
253
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
254
}
255
}
256
257
@PostMapping("/users")
258
public ResponseEntity<Void> createUser(@RequestBody String userJson) {
259
try {
260
LdapUserDetails user = objectMapper.readValue(userJson, LdapUserDetailsImpl.class);
261
// Create user logic here
262
return ResponseEntity.created(URI.create("/api/ldap/users/" + user.getUsername())).build();
263
} catch (JsonProcessingException e) {
264
return ResponseEntity.badRequest().build();
265
}
266
}
267
}
268
```
269
270
### Session Serialization
271
272
```java
273
@Configuration
274
@EnableRedisHttpSession
275
public class SessionConfig {
276
277
@Bean
278
public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
279
return new GenericJackson2JsonRedisSerializer(ldapObjectMapper());
280
}
281
282
private ObjectMapper ldapObjectMapper() {
283
ObjectMapper mapper = new ObjectMapper();
284
mapper.registerModule(new LdapJackson2Module());
285
mapper.activateDefaultTyping(
286
BasicPolymorphicTypeValidator.builder()
287
.allowIfSubType(Object.class)
288
.build(),
289
ObjectMapper.DefaultTyping.NON_FINAL
290
);
291
return mapper;
292
}
293
}
294
```