0
# Object Mapping Framework
1
2
The X-Content library provides a comprehensive declarative framework for converting structured content directly into Java objects with type safety and flexible construction patterns.
3
4
## Capabilities
5
6
### ObjectParser
7
8
Declarative, stateless parser for objects that use setter methods or field assignment.
9
10
```java { .api }
11
/**
12
* Declarative parser for objects with setter-based construction
13
* @param <Value> the type of object to parse
14
* @param <Context> the type of parsing context
15
*/
16
public final class ObjectParser<Value, Context> extends AbstractObjectParser<Value, Context> {
17
18
/**
19
* Create an object parser with automatic value creation
20
* @param name parser name for error messages
21
*/
22
public ObjectParser(String name);
23
24
/**
25
* Create an object parser with custom value supplier
26
* @param name parser name for error messages
27
* @param valueSupplier supplier to create new instances
28
*/
29
public ObjectParser(String name, Supplier<Value> valueSupplier);
30
31
/**
32
* Create an object parser with unknown field handling
33
* @param name parser name for error messages
34
* @param ignoreUnknownFields whether to ignore unknown fields
35
* @param valueSupplier supplier to create new instances
36
*/
37
public ObjectParser(String name, boolean ignoreUnknownFields, Supplier<Value> valueSupplier);
38
39
/**
40
* Parse content into a new object instance
41
* @param parser content parser
42
* @param context parsing context
43
* @return parsed object
44
*/
45
public Value parse(XContentParser parser, Context context) throws IOException;
46
47
/**
48
* Parse content into an existing object instance
49
* @param parser content parser
50
* @param value existing object to populate
51
* @param context parsing context
52
* @return the populated object
53
*/
54
public Value parse(XContentParser parser, Value value, Context context) throws IOException;
55
}
56
```
57
58
### Field Declaration Methods
59
60
Methods for declaring how to parse different field types.
61
62
```java { .api }
63
/**
64
* Declare a string field
65
* @param consumer setter method reference
66
* @param field parse field definition
67
*/
68
public void declareString(BiConsumer<Value, String> consumer, ParseField field);
69
70
/**
71
* Declare an integer field
72
* @param consumer setter method reference
73
* @param field parse field definition
74
*/
75
public void declareInt(BiConsumer<Value, Integer> consumer, ParseField field);
76
77
/**
78
* Declare a long field
79
* @param consumer setter method reference
80
* @param field parse field definition
81
*/
82
public void declareLong(BiConsumer<Value, Long> consumer, ParseField field);
83
84
/**
85
* Declare a float field
86
* @param consumer setter method reference
87
* @param field parse field definition
88
*/
89
public void declareFloat(BiConsumer<Value, Float> consumer, ParseField field);
90
91
/**
92
* Declare a double field
93
* @param consumer setter method reference
94
* @param field parse field definition
95
*/
96
public void declareDouble(BiConsumer<Value, Double> consumer, ParseField field);
97
98
/**
99
* Declare a boolean field
100
* @param consumer setter method reference
101
* @param field parse field definition
102
*/
103
public void declareBoolean(BiConsumer<Value, Boolean> consumer, ParseField field);
104
105
/**
106
* Declare an object field
107
* @param consumer setter method reference
108
* @param parser parser for the object type
109
* @param field parse field definition
110
*/
111
public <T> void declareObject(BiConsumer<Value, T> consumer, ContextParser<Context, T> parser, ParseField field);
112
113
/**
114
* Declare an array of objects field
115
* @param consumer setter method reference
116
* @param parser parser for individual array elements
117
* @param field parse field definition
118
*/
119
public <T> void declareObjectArray(BiConsumer<Value, List<T>> consumer, ContextParser<Context, T> parser, ParseField field);
120
121
/**
122
* Declare a named object field (using registry)
123
* @param consumer setter method reference
124
* @param namedObjectParser parser for named objects
125
* @param field parse field definition
126
*/
127
public <T> void declareNamedObject(BiConsumer<Value, T> consumer,
128
NamedObjectParser<T, Context> namedObjectParser, ParseField field);
129
130
/**
131
* Declare an array of named objects field
132
* @param consumer setter method reference
133
* @param namedObjectParser parser for individual named objects
134
* @param field parse field definition
135
*/
136
public <T> void declareNamedObjects(BiConsumer<Value, List<T>> consumer,
137
NamedObjectParser<T, Context> namedObjectParser, ParseField field);
138
139
/**
140
* Declare a field that can contain any type of value
141
* @param consumer setter method reference
142
* @param field parse field definition
143
*/
144
public void declareField(BiConsumer<Value, Object> consumer, ContextParser<Context, Object> parser,
145
ParseField field, ValueType expectedValueType);
146
```
147
148
**Usage Example:**
149
150
```java
151
import org.elasticsearch.xcontent.*;
152
153
// Define a simple data class
154
public class User {
155
private String name;
156
private int age;
157
private boolean active;
158
private List<String> skills;
159
private Address address;
160
161
// Constructor, getters, and setters...
162
public User() {}
163
public void setName(String name) { this.name = name; }
164
public void setAge(int age) { this.age = age; }
165
public void setActive(boolean active) { this.active = active; }
166
public void setSkills(List<String> skills) { this.skills = skills; }
167
public void setAddress(Address address) { this.address = address; }
168
}
169
170
public class Address {
171
private String street;
172
private String city;
173
174
public Address() {}
175
public void setStreet(String street) { this.street = street; }
176
public void setCity(String city) { this.city = city; }
177
}
178
179
// Create parsers
180
ObjectParser<Address, Void> addressParser = new ObjectParser<>("address", Address::new);
181
addressParser.declareString(Address::setStreet, new ParseField("street"));
182
addressParser.declareString(Address::setCity, new ParseField("city"));
183
184
ObjectParser<User, Void> userParser = new ObjectParser<>("user", User::new);
185
userParser.declareString(User::setName, new ParseField("name"));
186
userParser.declareInt(User::setAge, new ParseField("age"));
187
userParser.declareBoolean(User::setActive, new ParseField("active"));
188
userParser.declareStringArray(User::setSkills, new ParseField("skills"));
189
userParser.declareObject(User::setAddress, addressParser, new ParseField("address"));
190
191
// Parse JSON content
192
String json = """
193
{
194
"name": "John Doe",
195
"age": 30,
196
"active": true,
197
"skills": ["Java", "Elasticsearch"],
198
"address": {
199
"street": "123 Main St",
200
"city": "New York"
201
}
202
}
203
""";
204
205
XContentParser parser = XContentType.JSON.xContent()
206
.createParser(XContentParserConfiguration.EMPTY, json);
207
User user = userParser.parse(parser, null);
208
parser.close();
209
```
210
211
### ConstructingObjectParser
212
213
Parser for objects that require constructor arguments rather than setter methods.
214
215
```java { .api }
216
/**
217
* Parser for objects requiring constructor arguments
218
* @param <Value> the type of object to construct
219
* @param <Context> the type of parsing context
220
*/
221
public final class ConstructingObjectParser<Value, Context> extends AbstractObjectParser<Value, Context> {
222
223
/**
224
* Create a constructing parser with simple builder function
225
* @param name parser name for error messages
226
* @param builder function that constructs objects from argument array
227
*/
228
public ConstructingObjectParser(String name, Function<Object[], Value> builder);
229
230
/**
231
* Create a constructing parser with context-aware builder function
232
* @param name parser name for error messages
233
* @param ignoreUnknownFields whether to ignore unknown fields
234
* @param builder function that constructs objects from arguments and context
235
*/
236
public ConstructingObjectParser(String name, boolean ignoreUnknownFields,
237
BiFunction<Object[], Context, Value> builder);
238
239
/**
240
* Mark a field as a required constructor argument
241
* @return BiConsumer that marks the field as a constructor argument
242
*/
243
public static <Value, FieldT> BiConsumer<Value, FieldT> constructorArg();
244
245
/**
246
* Mark a field as an optional constructor argument
247
* @return BiConsumer that marks the field as an optional constructor argument
248
*/
249
public static <Value, FieldT> BiConsumer<Value, FieldT> optionalConstructorArg();
250
251
/**
252
* Parse content into a new object instance
253
* @param parser content parser
254
* @param context parsing context
255
* @return constructed object
256
*/
257
public Value parse(XContentParser parser, Context context) throws IOException;
258
}
259
```
260
261
**Usage Example:**
262
263
```java
264
// Immutable data class with constructor
265
public class ImmutableUser {
266
private final String name;
267
private final int age;
268
private final boolean active;
269
private final List<String> skills;
270
271
public ImmutableUser(String name, int age, boolean active, List<String> skills) {
272
this.name = name;
273
this.age = age;
274
this.active = active;
275
this.skills = skills;
276
}
277
278
// Getters only...
279
}
280
281
// Create constructing parser
282
ConstructingObjectParser<ImmutableUser, Void> parser = new ConstructingObjectParser<>(
283
"immutable_user",
284
args -> new ImmutableUser(
285
(String) args[0], // name
286
(Integer) args[1], // age
287
(Boolean) args[2], // active
288
(List<String>) args[3] // skills
289
)
290
);
291
292
// Declare fields as constructor arguments
293
parser.declareString(constructorArg(), new ParseField("name"));
294
parser.declareInt(constructorArg(), new ParseField("age"));
295
parser.declareBoolean(constructorArg(), new ParseField("active"));
296
parser.declareStringArray(constructorArg(), new ParseField("skills"));
297
298
// Parse content
299
XContentParser contentParser = XContentType.JSON.xContent()
300
.createParser(XContentParserConfiguration.EMPTY, jsonContent);
301
ImmutableUser user = parser.parse(contentParser, null);
302
contentParser.close();
303
```
304
305
### InstantiatingObjectParser
306
307
Parser that uses reflection to call constructors with `@ParserConstructor` annotation.
308
309
```java { .api }
310
/**
311
* Parser that uses reflection for object construction
312
* @param <Value> the type of object to instantiate
313
* @param <Context> the type of parsing context
314
*/
315
public class InstantiatingObjectParser<Value, Context>
316
implements BiFunction<XContentParser, Context, Value>, ContextParser<Context, Value> {
317
318
/**
319
* Builder for creating instantiating parsers
320
*/
321
public static class Builder<Value, Context> {
322
323
/**
324
* Create a builder for the specified class
325
* @param name parser name for error messages
326
* @param valueClass class to instantiate
327
* @return builder instance
328
*/
329
public static <Value, Context> Builder<Value, Context> builder(String name, Class<Value> valueClass);
330
331
/**
332
* Create a builder with unknown field handling
333
* @param name parser name for error messages
334
* @param ignoreUnknownFields whether to ignore unknown fields
335
* @param valueClass class to instantiate
336
* @return builder instance
337
*/
338
public static <Value, Context> Builder<Value, Context> builder(String name, boolean ignoreUnknownFields,
339
Class<Value> valueClass);
340
341
/**
342
* Build the parser
343
* @return InstantiatingObjectParser instance
344
*/
345
public InstantiatingObjectParser<Value, Context> build();
346
}
347
348
/**
349
* Parse content and instantiate object
350
* @param parser content parser
351
* @param context parsing context
352
* @return instantiated object
353
*/
354
public Value apply(XContentParser parser, Context context);
355
}
356
357
/**
358
* Annotation to mark constructors for automatic parsing
359
*/
360
@Target(ElementType.CONSTRUCTOR)
361
@Retention(RetentionPolicy.RUNTIME)
362
public @interface ParserConstructor {
363
}
364
```
365
366
**Usage Example:**
367
368
```java
369
// Data class with annotated constructor
370
public class AnnotatedUser {
371
private final String name;
372
private final int age;
373
private final boolean active;
374
375
@ParserConstructor
376
public AnnotatedUser(String name, int age, boolean active) {
377
this.name = name;
378
this.age = age;
379
this.active = active;
380
}
381
382
// Getters...
383
}
384
385
// Create instantiating parser
386
InstantiatingObjectParser<AnnotatedUser, Void> parser =
387
InstantiatingObjectParser.builder("annotated_user", AnnotatedUser.class).build();
388
389
// Parse content (field names must match constructor parameter names)
390
XContentParser contentParser = XContentType.JSON.xContent()
391
.createParser(XContentParserConfiguration.EMPTY, jsonContent);
392
AnnotatedUser user = parser.apply(contentParser, null);
393
contentParser.close();
394
```
395
396
### ValueType Enumeration
397
398
Enumeration defining supported value types for field declarations.
399
400
```java { .api }
401
/**
402
* Enumeration of supported value types for object parsing
403
*/
404
public enum ValueType {
405
STRING,
406
STRING_OR_NULL,
407
FLOAT,
408
FLOAT_OR_NULL,
409
DOUBLE,
410
DOUBLE_OR_NULL,
411
INT,
412
INT_OR_NULL,
413
LONG,
414
LONG_OR_NULL,
415
BOOLEAN,
416
BOOLEAN_OR_NULL,
417
STRING_ARRAY,
418
FLOAT_ARRAY,
419
DOUBLE_ARRAY,
420
INT_ARRAY,
421
LONG_ARRAY,
422
BOOLEAN_ARRAY,
423
OBJECT,
424
OBJECT_OR_NULL,
425
OBJECT_ARRAY,
426
OBJECT_ARRAY_OR_NULL,
427
VALUE,
428
VALUE_OR_NULL,
429
VALUE_ARRAY
430
}
431
```
432
433
### Parser Interfaces
434
435
```java { .api }
436
/**
437
* Interface for parsing objects with context
438
*/
439
@FunctionalInterface
440
public interface ContextParser<Context, T> {
441
/**
442
* Parse an object with the given context
443
* @param parser content parser
444
* @param context parsing context
445
* @return parsed object
446
*/
447
T parse(XContentParser parser, Context context) throws IOException;
448
}
449
450
/**
451
* Interface for parsing named objects
452
*/
453
public interface NamedObjectParser<T, Context> {
454
/**
455
* Parse a named object
456
* @param parser content parser
457
* @param context parsing context
458
* @param name object name
459
* @return parsed object
460
*/
461
T parse(XContentParser parser, Context context, String name) throws IOException;
462
}
463
464
/**
465
* Interface for consuming unknown fields during parsing
466
*/
467
@FunctionalInterface
468
public interface UnknownFieldConsumer<Value> {
469
/**
470
* Accept an unknown field
471
* @param objectParser the parser that encountered the unknown field
472
* @param value the object being parsed
473
* @param fieldName the unknown field name
474
* @param parser content parser positioned at the field value
475
*/
476
void accept(ObjectParser<Value, ?> objectParser, Value value, String fieldName, XContentParser parser);
477
}
478
```