0
# Object Serialization
1
2
Handle Java object serialization and deserialization with support for custom class loaders and closure-based processing for safe resource management.
3
4
## Capabilities
5
6
### Object Output Stream Operations
7
8
Create and manage ObjectOutputStream objects for writing serializable objects to files.
9
10
```java { .api }
11
/**
12
* Create an object output stream for this path
13
* @param self a Path object
14
* @return an object output stream
15
* @throws IOException if an IOException occurs
16
*/
17
ObjectOutputStream newObjectOutputStream(Path self);
18
19
/**
20
* Create a new ObjectOutputStream for this path and then pass it to the closure.
21
* This method ensures the stream is closed after the closure returns
22
* @param self a Path
23
* @param closure a closure
24
* @return the value returned by the closure
25
* @throws IOException if an IOException occurs
26
*/
27
<T> T withObjectOutputStream(Path self, Closure<T> closure);
28
```
29
30
**Usage Examples:**
31
32
```groovy
33
import java.nio.file.Path
34
import java.nio.file.Paths
35
36
Path objectFile = Paths.get("data.ser")
37
38
// Create object output stream (manual resource management)
39
ObjectOutputStream objOut = objectFile.newObjectOutputStream()
40
try {
41
objOut.writeObject("Hello, World!")
42
objOut.writeObject(42)
43
objOut.writeObject([1, 2, 3])
44
objOut.flush()
45
} finally {
46
objOut.close()
47
}
48
49
// Automatic resource management with closure
50
objectFile.withObjectOutputStream { objOut ->
51
objOut.writeObject("String data")
52
objOut.writeObject(new Date())
53
objOut.writeObject([name: "John", age: 30])
54
55
// Write multiple objects
56
def people = [
57
new Person("Alice", 25),
58
new Person("Bob", 30),
59
new Person("Charlie", 35)
60
]
61
objOut.writeObject(people)
62
}
63
64
// Serialize custom objects
65
class Configuration implements Serializable {
66
String hostname
67
int port
68
Map<String, String> properties
69
}
70
71
Path configFile = Paths.get("config.ser")
72
def config = new Configuration(
73
hostname: "localhost",
74
port: 8080,
75
properties: [debug: "true", timeout: "30"]
76
)
77
78
configFile.withObjectOutputStream { objOut ->
79
objOut.writeObject(config)
80
}
81
```
82
83
### Object Input Stream Operations
84
85
Create and manage ObjectInputStream objects for reading serializable objects from files.
86
87
```java { .api }
88
/**
89
* Create an object input stream for this file
90
* @param self a Path object
91
* @return an object input stream
92
* @throws IOException if an IOException occurs
93
*/
94
ObjectInputStream newObjectInputStream(Path self);
95
96
/**
97
* Create an object input stream for this path using the given class loader
98
* @param self a Path object
99
* @param classLoader the class loader to use when loading the class
100
* @return an object input stream
101
* @throws IOException if an IOException occurs
102
*/
103
ObjectInputStream newObjectInputStream(Path self, ClassLoader classLoader);
104
105
/**
106
* Create a new ObjectInputStream for this file and pass it to the closure.
107
* This method ensures the stream is closed after the closure returns
108
* @param path a Path
109
* @param closure a closure
110
* @return the value returned by the closure
111
* @throws IOException if an IOException occurs
112
*/
113
<T> T withObjectInputStream(Path path, Closure<T> closure);
114
115
/**
116
* Create a new ObjectInputStream for this file associated with the given class loader and pass it to the closure.
117
* This method ensures the stream is closed after the closure returns
118
* @param self a Path
119
* @param classLoader the class loader to use when loading the class
120
* @param closure a closure
121
* @return the value returned by the closure
122
* @throws IOException if an IOException occurs
123
*/
124
<T> T withObjectInputStream(Path self, ClassLoader classLoader, Closure<T> closure);
125
```
126
127
**Usage Examples:**
128
129
```groovy
130
import java.nio.file.Path
131
import java.nio.file.Paths
132
133
Path objectFile = Paths.get("data.ser")
134
135
// Create object input stream (manual resource management)
136
ObjectInputStream objIn = objectFile.newObjectInputStream()
137
try {
138
String stringData = objIn.readObject()
139
Integer intData = objIn.readObject()
140
List listData = objIn.readObject()
141
142
println "String: ${stringData}"
143
println "Integer: ${intData}"
144
println "List: ${listData}"
145
} finally {
146
objIn.close()
147
}
148
149
// Automatic resource management with closure
150
def objects = objectFile.withObjectInputStream { objIn ->
151
def result = []
152
try {
153
while (true) {
154
result << objIn.readObject()
155
}
156
} catch (EOFException e) {
157
// Expected when reaching end of file
158
}
159
return result
160
}
161
162
println "Read ${objects.size()} objects: ${objects}"
163
164
// Deserialize with custom class loader
165
ClassLoader customLoader = new URLClassLoader([new File("custom-classes").toURI().toURL()] as URL[])
166
167
objectFile.withObjectInputStream(customLoader) { objIn ->
168
def customObject = objIn.readObject()
169
println "Loaded custom object: ${customObject}"
170
}
171
172
// Read configuration object
173
Path configFile = Paths.get("config.ser")
174
Configuration config = configFile.withObjectInputStream { objIn ->
175
objIn.readObject() as Configuration
176
}
177
178
println "Loaded config: ${config.hostname}:${config.port}"
179
config.properties.each { key, value ->
180
println " ${key} = ${value}"
181
}
182
```
183
184
### Object Iteration
185
186
Iterate through objects in a serialized file using closures.
187
188
```java { .api }
189
/**
190
* Iterates through the given file object by object
191
* @param self a Path object
192
* @param closure a closure
193
* @throws IOException if an IOException occurs
194
* @throws ClassNotFoundException if the class is not found
195
*/
196
void eachObject(Path self, Closure closure);
197
```
198
199
**Usage Examples:**
200
201
```groovy
202
import java.nio.file.Path
203
import java.nio.file.Paths
204
205
Path objectFile = Paths.get("multiple-objects.ser")
206
207
// First, write multiple objects
208
objectFile.withObjectOutputStream { objOut ->
209
objOut.writeObject("First object")
210
objOut.writeObject(42)
211
objOut.writeObject([name: "Alice", age: 25])
212
objOut.writeObject(new Date())
213
objOut.writeObject([1, 2, 3, 4, 5])
214
}
215
216
// Iterate through all objects in the file
217
objectFile.eachObject { obj ->
218
println "Object type: ${obj.class.simpleName}, value: ${obj}"
219
}
220
221
// Process specific object types
222
objectFile.eachObject { obj ->
223
switch (obj) {
224
case String:
225
println "Found string: '${obj}'"
226
break
227
case Number:
228
println "Found number: ${obj} (${obj.class.simpleName})"
229
break
230
case List:
231
println "Found list with ${obj.size()} elements: ${obj}"
232
break
233
case Map:
234
println "Found map with keys: ${obj.keySet()}"
235
break
236
case Date:
237
println "Found date: ${obj.format('yyyy-MM-dd HH:mm:ss')}"
238
break
239
default:
240
println "Found other object: ${obj} (${obj.class.name})"
241
}
242
}
243
244
// Count objects by type
245
def typeCounts = [:]
246
objectFile.eachObject { obj ->
247
String typeName = obj.class.simpleName
248
typeCounts[typeName] = (typeCounts[typeName] ?: 0) + 1
249
}
250
251
println "Object type summary:"
252
typeCounts.each { type, count ->
253
println " ${type}: ${count}"
254
}
255
256
// Filter and collect specific objects
257
def stringObjects = []
258
def numberObjects = []
259
260
objectFile.eachObject { obj ->
261
if (obj instanceof String) {
262
stringObjects << obj
263
} else if (obj instanceof Number) {
264
numberObjects << obj
265
}
266
}
267
268
println "String objects: ${stringObjects}"
269
println "Number objects: ${numberObjects}"
270
```
271
272
### Complex Serialization Examples
273
274
Advanced examples demonstrating real-world usage patterns.
275
276
**Usage Examples:**
277
278
```groovy
279
import java.nio.file.Path
280
import java.nio.file.Paths
281
282
// Serialize application state
283
class ApplicationState implements Serializable {
284
String version
285
Map<String, Object> settings
286
List<String> recentFiles
287
Date lastSaved
288
}
289
290
Path stateFile = Paths.get("app-state.ser")
291
292
// Save application state
293
def currentState = new ApplicationState(
294
version: "1.0.0",
295
settings: [theme: "dark", language: "en", autoSave: true],
296
recentFiles: ["/home/user/doc1.txt", "/home/user/doc2.txt"],
297
lastSaved: new Date()
298
)
299
300
stateFile.withObjectOutputStream { objOut ->
301
objOut.writeObject(currentState)
302
}
303
304
// Load application state
305
ApplicationState loadedState = stateFile.withObjectInputStream { objIn ->
306
objIn.readObject() as ApplicationState
307
}
308
309
println "Loaded application state:"
310
println " Version: ${loadedState.version}"
311
println " Settings: ${loadedState.settings}"
312
println " Recent files: ${loadedState.recentFiles}"
313
println " Last saved: ${loadedState.lastSaved}"
314
315
// Serialize a cache of objects
316
Path cacheFile = Paths.get("object-cache.ser")
317
318
// Write cache
319
def cache = [
320
"user:123": [id: 123, name: "Alice", email: "alice@example.com"],
321
"user:456": [id: 456, name: "Bob", email: "bob@example.com"],
322
"config:main": [timeout: 30, retries: 3, debug: false]
323
]
324
325
cacheFile.withObjectOutputStream { objOut ->
326
cache.each { key, value ->
327
objOut.writeObject([key: key, value: value])
328
}
329
}
330
331
// Read cache
332
def loadedCache = [:]
333
cacheFile.eachObject { entry ->
334
loadedCache[entry.key] = entry.value
335
}
336
337
println "Loaded cache entries:"
338
loadedCache.each { key, value ->
339
println " ${key}: ${value}"
340
}
341
342
// Serialize with versioning for backward compatibility
343
class VersionedData implements Serializable {
344
private static final long serialVersionUID = 1L
345
346
int version = 1
347
String data
348
Map<String, Object> metadata
349
350
// Custom serialization for version handling
351
private void writeObject(ObjectOutputStream out) throws IOException {
352
out.defaultWriteObject()
353
}
354
355
private void readObject(ObjectInputStream input) throws IOException, ClassNotFoundException {
356
input.defaultReadObject()
357
// Handle version-specific logic here
358
if (version < 1) {
359
// Upgrade old data format
360
metadata = metadata ?: [:]
361
}
362
}
363
}
364
```