or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

directory-operations.mdfile-appending.mdfile-io.mdindex.mdline-processing.mdobject-serialization.mdstream-operations.md

object-serialization.mddocs/

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

```