or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

annotation-generation.mdbuilders.mdextensions.mdindex.mdmemoization.mdpretty-strings.mdserialization.mdstandalone-builders.mdtagged-unions.mdvalue-classes.md

serialization.mddocs/

0

# Serialization

1

2

The @SerializableAutoValue annotation generates serializable implementations for AutoValue classes that contain non-serializable fields like Optional, ImmutableList, or other modern Java types.

3

4

## Basic Serializable AutoValue

5

6

```java { .api }

7

@SerializableAutoValue

8

@AutoValue

9

public abstract class Person implements Serializable {

10

public abstract String name();

11

public abstract Optional<String> email();

12

public abstract ImmutableList<String> hobbies();

13

14

public static Person create(String name, Optional<String> email, ImmutableList<String> hobbies) {

15

return new AutoValue_Person(name, email, hobbies);

16

}

17

}

18

```

19

20

The generated code automatically handles serialization of:

21

- `Optional<T>` fields

22

- `ImmutableList<T>`, `ImmutableSet<T>`, `ImmutableMap<K,V>`

23

- Other common non-serializable types

24

25

## Usage Example

26

27

```java

28

Person person = Person.create(

29

"Alice",

30

Optional.of("alice@example.com"),

31

ImmutableList.of("reading", "coding", "hiking"));

32

33

// Serialize to bytes

34

ByteArrayOutputStream baos = new ByteArrayOutputStream();

35

ObjectOutputStream oos = new ObjectOutputStream(baos);

36

oos.writeObject(person);

37

byte[] serialized = baos.toByteArray();

38

39

// Deserialize from bytes

40

ByteArrayInputStream bais = new ByteArrayInputStream(serialized);

41

ObjectInputStream ois = new ObjectInputStream(bais);

42

Person deserialized = (Person) ois.readObject();

43

44

System.out.println(person.equals(deserialized)); // true

45

```

46

47

## Supported Types

48

49

The serialization extension automatically handles these non-serializable types:

50

51

```java { .api }

52

@SerializableAutoValue

53

@AutoValue

54

public abstract class TypesExample implements Serializable {

55

// Optional types

56

public abstract Optional<String> optionalString();

57

public abstract OptionalInt optionalInt();

58

public abstract OptionalLong optionalLong();

59

public abstract OptionalDouble optionalDouble();

60

61

// Guava Immutable Collections

62

public abstract ImmutableList<String> list();

63

public abstract ImmutableSet<Integer> set();

64

public abstract ImmutableMap<String, Object> map();

65

public abstract ImmutableMultimap<String, String> multimap();

66

public abstract ImmutableTable<String, String, Object> table();

67

68

// Other Guava types

69

public abstract ImmutableRangeSet<Integer> rangeSet();

70

public abstract ImmutableRangeMap<Integer, String> rangeMap();

71

72

public static TypesExample create(

73

Optional<String> optionalString,

74

OptionalInt optionalInt,

75

OptionalLong optionalLong,

76

OptionalDouble optionalDouble,

77

ImmutableList<String> list,

78

ImmutableSet<Integer> set,

79

ImmutableMap<String, Object> map,

80

ImmutableMultimap<String, String> multimap,

81

ImmutableTable<String, String, Object> table,

82

ImmutableRangeSet<Integer> rangeSet,

83

ImmutableRangeMap<Integer, String> rangeMap) {

84

return new AutoValue_TypesExample(

85

optionalString, optionalInt, optionalLong, optionalDouble,

86

list, set, map, multimap, table, rangeSet, rangeMap);

87

}

88

}

89

```

90

91

## Nested Serializable AutoValue

92

93

SerializableAutoValue works with nested AutoValue objects:

94

95

```java { .api }

96

@SerializableAutoValue

97

@AutoValue

98

public abstract class Address implements Serializable {

99

public abstract String street();

100

public abstract String city();

101

public abstract Optional<String> zipCode();

102

103

public static Address create(String street, String city, Optional<String> zipCode) {

104

return new AutoValue_Address(street, city, zipCode);

105

}

106

}

107

108

@SerializableAutoValue

109

@AutoValue

110

public abstract class Company implements Serializable {

111

public abstract String name();

112

public abstract Address headquarters();

113

public abstract ImmutableList<Address> offices();

114

public abstract ImmutableMap<String, Optional<String>> contacts();

115

116

public static Company create(

117

String name,

118

Address headquarters,

119

ImmutableList<Address> offices,

120

ImmutableMap<String, Optional<String>> contacts) {

121

return new AutoValue_Company(name, headquarters, offices, contacts);

122

}

123

}

124

```

125

126

## Custom Serializer Extensions

127

128

Create custom serializers for types not supported by default:

129

130

```java { .api }

131

// Custom type that needs serialization support

132

public class CustomType {

133

private final String data;

134

135

public CustomType(String data) {

136

this.data = data;

137

}

138

139

public String getData() {

140

return data;

141

}

142

}

143

144

// Custom serializer extension

145

public class CustomTypeSerializerExtension implements SerializerExtension {

146

@Override

147

public Optional<Serializer> getSerializer(

148

TypeMirror typeMirror,

149

SerializerFactory factory) {

150

if (isCustomType(typeMirror)) {

151

return Optional.of(new CustomTypeSerializer());

152

}

153

return Optional.empty();

154

}

155

156

private boolean isCustomType(TypeMirror type) {

157

return type.toString().equals(CustomType.class.getName());

158

}

159

160

private static class CustomTypeSerializer implements Serializer {

161

@Override

162

public TypeMirror proxyFieldType() {

163

return getTypeMirror(String.class);

164

}

165

166

@Override

167

public CodeBlock toProxy(CodeBlock expression) {

168

return CodeBlock.of("$L.getData()", expression);

169

}

170

171

@Override

172

public CodeBlock fromProxy(CodeBlock expression) {

173

return CodeBlock.of("new $T($L)", CustomType.class, expression);

174

}

175

}

176

}

177

```

178

179

Register the extension in `META-INF/services/com.google.auto.value.extension.serializable.serializer.interfaces.SerializerExtension`.

180

181

## Serialization with Builders

182

183

SerializableAutoValue works seamlessly with builders:

184

185

```java { .api }

186

@SerializableAutoValue

187

@AutoValue

188

public abstract class Configuration implements Serializable {

189

public abstract String host();

190

public abstract Optional<Integer> port();

191

public abstract ImmutableSet<String> features();

192

public abstract ImmutableMap<String, String> properties();

193

194

public static Builder builder() {

195

return new AutoValue_Configuration.Builder()

196

.features(ImmutableSet.of())

197

.properties(ImmutableMap.of());

198

}

199

200

@AutoValue.Builder

201

public abstract static class Builder {

202

public abstract Builder host(String host);

203

public abstract Builder port(int port);

204

public abstract Builder features(Iterable<String> features);

205

public abstract Builder properties(Map<String, String> properties);

206

207

public abstract Builder addFeature(String feature);

208

public abstract Builder putProperty(String key, String value);

209

210

public abstract Configuration build();

211

}

212

}

213

```

214

215

Serialization works with builder-created objects:

216

217

```java

218

Configuration config = Configuration.builder()

219

.host("localhost")

220

.port(8080)

221

.addFeature("ssl")

222

.addFeature("compression")

223

.putProperty("timeout", "5000")

224

.build();

225

226

// Serialize and deserialize

227

byte[] serialized = serialize(config);

228

Configuration deserialized = deserialize(serialized);

229

System.out.println(config.equals(deserialized)); // true

230

```

231

232

## Generic SerializableAutoValue

233

234

Serialization supports generic types:

235

236

```java { .api }

237

@SerializableAutoValue

238

@AutoValue

239

public abstract class Container<T> implements Serializable {

240

public abstract T value();

241

public abstract Optional<String> label();

242

public abstract ImmutableList<T> alternatives();

243

244

public static <T> Container<T> create(

245

T value,

246

Optional<String> label,

247

ImmutableList<T> alternatives) {

248

return new AutoValue_Container<>(value, label, alternatives);

249

}

250

}

251

```

252

253

Usage with serialization:

254

255

```java

256

Container<String> stringContainer = Container.create(

257

"main value",

258

Optional.of("primary"),

259

ImmutableList.of("alt1", "alt2"));

260

261

// Serialization preserves generic type information

262

byte[] serialized = serialize(stringContainer);

263

Container<String> deserialized = deserialize(serialized);

264

```

265

266

## Error Handling

267

268

SerializableAutoValue provides clear errors for unsupported types:

269

270

```java

271

@SerializableAutoValue

272

@AutoValue

273

public abstract class UnsupportedExample implements Serializable {

274

// This will cause a compilation error

275

public abstract NonSerializableCustomType customField(); // ERROR: No serializer found

276

277

public static UnsupportedExample create(NonSerializableCustomType customField) {

278

return new AutoValue_UnsupportedExample(customField);

279

}

280

}

281

```

282

283

The error message will indicate which type needs a custom serializer.

284

285

## Serialization Performance

286

287

The generated serialization code is optimized:

288

289

- Uses direct field access (no reflection at runtime)

290

- Minimal object creation during serialization

291

- Efficient proxy objects for complex types

292

- Lazy initialization of serialization metadata

293

294

## Version Compatibility

295

296

Handle serialization version compatibility:

297

298

```java { .api }

299

@SerializableAutoValue

300

@AutoValue

301

public abstract class VersionedData implements Serializable {

302

private static final long serialVersionUID = 1L;

303

304

public abstract String name();

305

public abstract Optional<String> description();

306

public abstract ImmutableList<String> tags();

307

308

// Method to handle version compatibility

309

private Object readResolve() {

310

// Custom logic for handling old versions

311

return this;

312

}

313

314

public static VersionedData create(String name, Optional<String> description, ImmutableList<String> tags) {

315

return new AutoValue_VersionedData(name, description, tags);

316

}

317

}

318

```

319

320

## Integration with Other Extensions

321

322

SerializableAutoValue can be combined with other extensions:

323

324

```java { .api }

325

@SerializableAutoValue

326

@AutoValue

327

public abstract class CachedSerializableData implements Serializable {

328

public abstract String data();

329

public abstract Optional<ImmutableList<Integer>> values();

330

331

@Memoized

332

public String processedData() {

333

return data().toUpperCase().trim();

334

}

335

336

@Memoized

337

@Override

338

public abstract String toString();

339

340

public static CachedSerializableData create(String data, Optional<ImmutableList<Integer>> values) {

341

return new AutoValue_CachedSerializableData(data, values);

342

}

343

}

344

```

345

346

The memoized fields are properly handled during serialization/deserialization.

347

348

## Restrictions

349

350

- The AutoValue class must implement `Serializable`

351

- All custom types in properties must either be serializable or have custom serializers

352

- Generic type parameters must be serializable at runtime

353

- Builder classes are not automatically serializable (only the built objects are)