0
# JSON Building
1
2
DSL-based JSON building with Groovy's closure syntax, supporting both in-memory and streaming approaches for flexible JSON construction.
3
4
## Capabilities
5
6
### JsonBuilder
7
8
In-memory JSON builder using Groovy's dynamic method invocation and closure syntax for intuitive JSON construction.
9
10
```java { .api }
11
/**
12
* In-memory JSON builder with DSL syntax support
13
*/
14
public class JsonBuilder extends GroovyObjectSupport implements Writable {
15
/** Default constructor */
16
public JsonBuilder();
17
18
/** Constructor with custom JSON generator */
19
public JsonBuilder(JsonGenerator generator);
20
21
/** Constructor with initial content */
22
public JsonBuilder(Object content);
23
public JsonBuilder(Object content, JsonGenerator generator);
24
25
/** Get the internal content structure */
26
public Object getContent();
27
28
/** Create root JSON object from Map */
29
public Object call(Map m);
30
31
/** Create root JSON array from List */
32
public Object call(List l);
33
34
/** Create root JSON array from varargs */
35
public Object call(Object... args);
36
37
/** Create array applying closure to collection */
38
public Object call(Iterable coll, Closure c);
39
public Object call(Collection coll, Closure c);
40
41
/** Create root JSON object from closure */
42
public Object call(Closure c);
43
44
/** Dynamic method calls for JSON structure building */
45
public Object invokeMethod(String name, Object args);
46
47
/** Serialize to JSON string */
48
public String toString();
49
50
/** Pretty-print JSON with formatting */
51
public String toPrettyString();
52
53
/** Write JSON to Writer (Writable interface) */
54
public Writer writeTo(Writer out) throws IOException;
55
}
56
```
57
58
**Usage Examples:**
59
60
```java
61
import groovy.json.JsonBuilder;
62
63
// Basic object construction
64
JsonBuilder json = new JsonBuilder();
65
json.user {
66
name "Alice"
67
age 30
68
email "alice@example.com"
69
}
70
String result = json.toString();
71
// {"user":{"name":"Alice","age":30,"email":"alice@example.com"}}
72
73
// Nested structures
74
JsonBuilder json = new JsonBuilder();
75
json.company {
76
name "ACME Corp"
77
employees {
78
engineering([
79
[name: "Bob", role: "Senior Developer"],
80
[name: "Carol", role: "Tech Lead"]
81
])
82
marketing([
83
[name: "David", role: "Manager"]
84
])
85
}
86
headquarters {
87
street "123 Main St"
88
city "San Francisco"
89
state "CA"
90
zipCode "94102"
91
}
92
}
93
94
// Array construction
95
JsonBuilder json = new JsonBuilder();
96
json([
97
[id: 1, title: "First Post", published: true],
98
[id: 2, title: "Draft Post", published: false]
99
]);
100
101
// Using collections with closures
102
List<String> names = ["Alice", "Bob", "Charlie"];
103
JsonBuilder json = new JsonBuilder();
104
json.users(names) { name ->
105
[
106
username: name.toLowerCase(),
107
displayName: name,
108
active: true
109
]
110
}
111
112
// From existing data
113
Map<String, Object> userData = [
114
id: 123,
115
name: "John Doe",
116
preferences: [theme: "dark", notifications: true]
117
];
118
JsonBuilder json = new JsonBuilder(userData);
119
```
120
121
### StreamingJsonBuilder
122
123
Memory-efficient JSON builder that writes directly to a Writer, ideal for large JSON documents.
124
125
```java { .api }
126
/**
127
* Memory-efficient streaming JSON builder
128
*/
129
public class StreamingJsonBuilder extends GroovyObjectSupport {
130
/** Constructor with Writer */
131
public StreamingJsonBuilder(Writer writer);
132
133
/** Constructor with Writer and custom generator */
134
public StreamingJsonBuilder(Writer writer, JsonGenerator generator);
135
136
/** Constructor with Writer and initial content */
137
public StreamingJsonBuilder(Writer writer, Object content) throws IOException;
138
public StreamingJsonBuilder(Writer writer, Object content, JsonGenerator generator) throws IOException;
139
140
/** Write Map as JSON object */
141
public Object call(Map m) throws IOException;
142
143
/** Write empty object with name */
144
public void call(String name) throws IOException;
145
146
/** Write List as JSON array */
147
public Object call(List l) throws IOException;
148
149
/** Write varargs as JSON array */
150
public Object call(Object... args) throws IOException;
151
152
/** Write collection with closure transformation */
153
public Object call(Iterable coll, Closure c) throws IOException;
154
public Object call(Collection coll, Closure c) throws IOException;
155
156
/** Write closure as JSON object */
157
public Object call(Closure c) throws IOException;
158
159
/** Write named object from closure */
160
public void call(String name, Closure c) throws IOException;
161
162
/** Write named array with closure transformation */
163
public void call(String name, Iterable coll, Closure c) throws IOException;
164
public void call(String name, Collection coll, Closure c) throws IOException;
165
166
/** Write named object merging map and closure */
167
public void call(String name, Map map, Closure callable) throws IOException;
168
169
/** Dynamic method calls for JSON structure */
170
public Object invokeMethod(String name, Object args);
171
}
172
```
173
174
**Usage Examples:**
175
176
```java
177
import groovy.json.StreamingJsonBuilder;
178
import java.io.StringWriter;
179
import java.io.FileWriter;
180
181
// Basic streaming to StringWriter
182
StringWriter writer = new StringWriter();
183
StreamingJsonBuilder json = new StreamingJsonBuilder(writer);
184
json.user {
185
id 123
186
name "Alice"
187
roles(["admin", "user"])
188
}
189
String result = writer.toString();
190
191
// Streaming large datasets to file
192
FileWriter fileWriter = new FileWriter("large-data.json");
193
StreamingJsonBuilder json = new StreamingJsonBuilder(fileWriter);
194
195
json.response {
196
status "success"
197
data {
198
// Stream large collection without loading all into memory
199
users(userRepository.streamAll()) { user ->
200
[
201
id: user.getId(),
202
name: user.getName(),
203
email: user.getEmail()
204
]
205
}
206
}
207
metadata {
208
generatedAt new Date()
209
count userRepository.count()
210
}
211
}
212
fileWriter.close();
213
214
// Streaming with named elements
215
StringWriter writer = new StringWriter();
216
StreamingJsonBuilder json = new StreamingJsonBuilder(writer);
217
json {
218
call("timestamp", System.currentTimeMillis())
219
call("data", dataList) { item ->
220
[processed: processItem(item), index: dataList.indexOf(item)]
221
}
222
}
223
```
224
225
### StreamingJsonDelegate
226
227
Internal delegate class for streaming JSON operations, exposed for advanced usage patterns.
228
229
```java { .api }
230
/**
231
* Delegate for streaming JSON building operations
232
*/
233
public static class StreamingJsonDelegate extends GroovyObjectSupport {
234
/** Constructor */
235
public StreamingJsonDelegate(Writer w, boolean first);
236
public StreamingJsonDelegate(Writer w, boolean first, JsonGenerator generator);
237
238
/** Get underlying writer */
239
public Writer getWriter();
240
241
/** Dynamic method handling for JSON structure */
242
public Object invokeMethod(String name, Object args);
243
244
/** Write named array */
245
public void call(String name, List<Object> list) throws IOException;
246
public void call(String name, Object... array) throws IOException;
247
248
/** Write named array with closure transformation */
249
public void call(String name, Iterable coll, Closure c) throws IOException;
250
public void call(String name, Collection coll, Closure c) throws IOException;
251
252
/** Write named value */
253
public void call(String name, Object value) throws IOException;
254
255
/** Write named object with closure */
256
public void call(String name, Object value, Closure callable) throws IOException;
257
public void call(String name, Closure value) throws IOException;
258
259
/** Write unescaped JSON */
260
public void call(String name, JsonOutput.JsonUnescaped json) throws IOException;
261
262
/** Write Writable as value */
263
public void call(String name, Writable json) throws IOException;
264
}
265
```
266
267
### JsonDelegate
268
269
Utility delegate for closures representing JSON objects, enabling Groovy's DSL syntax. This class is used internally by JsonBuilder to provide the dynamic method invocation capabilities.
270
271
```java { .api }
272
/**
273
* Delegate for closures representing JSON objects
274
*/
275
public class JsonDelegate extends GroovyObjectSupport {
276
/** Constructor */
277
public JsonDelegate();
278
279
/** Intercept method calls for JSON key/value pairs */
280
public Object invokeMethod(String name, Object args);
281
282
/** Get content map */
283
public Map<String, Object> getContent();
284
285
/** Create delegate from closure */
286
public static Map<String, Object> cloneDelegateAndGetContent(Closure<?> c);
287
288
/** Create delegate with curried closure */
289
public static Map<String, Object> curryDelegateAndGetContent(Closure<?> c, Object o);
290
291
/** Create delegate with generator and curried closure */
292
public static Map<String, Object> curryDelegateAndGetContent(Closure<?> c, Object o, JsonGenerator generator);
293
}
294
```
295
296
**Usage Examples:**
297
298
```java
299
import groovy.json.JsonDelegate;
300
import groovy.json.JsonGenerator;
301
302
// Direct usage (advanced)
303
JsonDelegate delegate = new JsonDelegate();
304
Closure<?> jsonClosure = {
305
name "John"
306
age 30
307
address {
308
street "123 Main St"
309
city "New York"
310
}
311
}
312
313
Map<String, Object> content = JsonDelegate.cloneDelegateAndGetContent(jsonClosure);
314
// Results in Map structure representing the JSON object
315
316
// Used internally by JsonBuilder for DSL support
317
// This enables the natural Groovy syntax:
318
// json.user { name "Alice"; age 25 }
319
```
320
321
## Advanced Building Patterns
322
323
### Custom JSON Generators
324
325
```java
326
import groovy.json.JsonGenerator;
327
328
// Create custom generator with options
329
JsonGenerator generator = new JsonGenerator.Options()
330
.excludeNulls()
331
.dateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
332
.disableUnicodeEscaping()
333
.build();
334
335
JsonBuilder json = new JsonBuilder(generator);
336
json.event {
337
timestamp new Date()
338
description "Test event"
339
metadata null // Will be excluded
340
}
341
```
342
343
### Memory Management for Large Documents
344
345
```java
346
// Use streaming builder for large datasets
347
FileWriter writer = new FileWriter("output.json");
348
StreamingJsonBuilder stream = new StreamingJsonBuilder(writer);
349
350
stream.largeDataset {
351
// Process data in chunks to avoid memory issues
352
for (int i = 0; i < 1000000; i += 1000) {
353
List<Object> chunk = dataService.getChunk(i, 1000);
354
call("batch_" + (i/1000), chunk) { item ->
355
[id: item.id, processed: processItem(item)]
356
}
357
}
358
}
359
writer.close();
360
```
361
362
### Complex Nested Structures
363
364
```java
365
JsonBuilder json = new JsonBuilder();
366
json {
367
apiVersion "v1"
368
kind "ConfigMap"
369
metadata {
370
name "app-config"
371
namespace "production"
372
labels {
373
app "myapp"
374
environment "prod"
375
}
376
}
377
data {
378
"database.url" "jdbc:postgresql://db:5432/myapp"
379
"cache.ttl" "3600"
380
"features" {
381
enabled(["feature-a", "feature-b"])
382
disabled(["feature-c"])
383
}
384
}
385
}
386
```
387
388
## Error Handling
389
390
JSON building operations can throw `IOException` for streaming operations or `JsonException` for malformed data:
391
392
```java
393
try {
394
FileWriter writer = new FileWriter("output.json");
395
StreamingJsonBuilder json = new StreamingJsonBuilder(writer);
396
json.data {
397
value "some data"
398
}
399
writer.close();
400
} catch (IOException e) {
401
System.err.println("I/O error during JSON writing: " + e.getMessage());
402
}
403
```