or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-operations.mdindex.mdindexing.mdquerying-views.mdserialization.mdstorage-implementations.mdtype-information.md

serialization.mddocs/

0

# Serialization

1

2

JSON-based object serialization with compression and custom ObjectMapper support. The serialization system handles converting Java objects to byte arrays for storage and retrieval.

3

4

## Capabilities

5

6

### KVStoreSerializer

7

8

Core serialization class that handles converting objects to and from byte arrays using Jackson JSON serialization with GZIP compression.

9

10

```java { .api }

11

/**

12

* Serializer used to translate between app-defined types and the LevelDB store.

13

*

14

* The serializer is based on Jackson, so values are written as JSON. It also allows "naked strings"

15

* and integers to be written as values directly, which will be written as UTF-8 strings.

16

*/

17

public class KVStoreSerializer {

18

/**

19

* Object mapper used to process app-specific types. If an application requires a specific

20

* configuration of the mapper, it can subclass this serializer and add custom configuration

21

* to this object.

22

*/

23

protected final ObjectMapper mapper;

24

25

/**

26

* Creates a new serializer with default Jackson ObjectMapper configuration.

27

*/

28

public KVStoreSerializer();

29

}

30

```

31

32

**Default Behavior:**

33

- Uses Jackson ObjectMapper for JSON serialization

34

- Applies GZIP compression to reduce storage size

35

- Special handling for String values (stored as UTF-8 without compression)

36

- Automatic data compression for space efficiency

37

38

### Object Serialization

39

40

Convert Java objects to byte arrays for storage, with automatic compression for non-string values.

41

42

```java { .api }

43

/**

44

* Serialize an object to bytes for storage.

45

* @param o - The object to serialize. Strings are stored as UTF-8, other objects as compressed JSON.

46

* @return Byte array representation of the object

47

* @throws Exception If serialization fails

48

*/

49

public final byte[] serialize(Object o) throws Exception;

50

```

51

52

**Usage Examples:**

53

54

```java

55

KVStoreSerializer serializer = new KVStoreSerializer();

56

57

// Serialize a simple string (stored as UTF-8, no compression)

58

String text = "Hello, World!";

59

byte[] stringBytes = serializer.serialize(text);

60

61

// Serialize a complex object (stored as compressed JSON)

62

Person person = new Person("p1", "Alice", 30);

63

byte[] personBytes = serializer.serialize(person);

64

65

// Serialize numbers and primitives

66

Integer number = 42;

67

byte[] numberBytes = serializer.serialize(number);

68

69

// Serialize collections

70

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

71

byte[] listBytes = serializer.serialize(names);

72

73

// Serialize maps

74

Map<String, Integer> scores = new HashMap<>();

75

scores.put("Alice", 95);

76

scores.put("Bob", 87);

77

byte[] mapBytes = serializer.serialize(scores);

78

```

79

80

### Object Deserialization

81

82

Convert byte arrays back to Java objects, with automatic decompression and type handling.

83

84

```java { .api }

85

/**

86

* Deserialize bytes back to an object of the specified type.

87

* @param data - The byte array to deserialize

88

* @param klass - The target class type

89

* @return The deserialized object

90

* @throws Exception If deserialization fails

91

*/

92

public final <T> T deserialize(byte[] data, Class<T> klass) throws Exception;

93

```

94

95

**Usage Examples:**

96

97

```java

98

KVStoreSerializer serializer = new KVStoreSerializer();

99

100

// Deserialize string

101

byte[] stringBytes = /* ... */;

102

String text = serializer.deserialize(stringBytes, String.class);

103

104

// Deserialize complex object

105

byte[] personBytes = /* ... */;

106

Person person = serializer.deserialize(personBytes, Person.class);

107

108

// Deserialize numbers

109

byte[] numberBytes = /* ... */;

110

Integer number = serializer.deserialize(numberBytes, Integer.class);

111

112

// Deserialize collections (requires generic type handling)

113

byte[] listBytes = /* ... */;

114

// Note: For generic collections, you may need TypeReference with Jackson

115

List<String> names = serializer.deserialize(listBytes, List.class);

116

117

// Deserialize maps

118

byte[] mapBytes = /* ... */;

119

Map<String, Integer> scores = serializer.deserialize(mapBytes, Map.class);

120

```

121

122

### Long Value Serialization

123

124

Special handling for long values used internally by the store for counters and metadata.

125

126

```java { .api }

127

/**

128

* Serialize a long value to bytes.

129

* @param value - The long value to serialize

130

* @return Byte array representation of the long

131

*/

132

final byte[] serialize(long value);

133

134

/**

135

* Deserialize bytes back to a long value.

136

* @param data - The byte array to deserialize

137

* @return The long value

138

*/

139

final long deserializeLong(byte[] data);

140

```

141

142

**Usage Examples:**

143

144

```java

145

KVStoreSerializer serializer = new KVStoreSerializer();

146

147

// Serialize long values (used internally for counters)

148

long counter = 12345L;

149

byte[] counterBytes = serializer.serialize(counter);

150

151

// Deserialize long values

152

long retrievedCounter = serializer.deserializeLong(counterBytes);

153

System.out.println("Counter: " + retrievedCounter);

154

```

155

156

### Custom Serializer Configuration

157

158

Create custom serializers by subclassing KVStoreSerializer to configure Jackson ObjectMapper behavior.

159

160

**Usage Examples:**

161

162

```java

163

// Custom serializer with specific Jackson configuration

164

public class CustomKVStoreSerializer extends KVStoreSerializer {

165

public CustomKVStoreSerializer() {

166

super();

167

// Configure the mapper for custom behavior

168

mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

169

mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

170

mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));

171

172

// Add custom modules

173

mapper.registerModule(new JavaTimeModule());

174

175

// Configure property naming strategy

176

mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);

177

}

178

}

179

180

// Use custom serializer with LevelDB

181

KVStoreSerializer customSerializer = new CustomKVStoreSerializer();

182

KVStore store = new LevelDB(new File("./custom-store"), customSerializer);

183

184

// Objects will be serialized using custom configuration

185

Person person = new Person("p1", "Alice", 30);

186

person.birthDate = LocalDateTime.now();

187

store.write(person); // Uses custom date formatting and snake_case properties

188

```

189

190

### Jackson Annotations Support

191

192

The serializer supports all Jackson annotations for controlling serialization behavior.

193

194

**Usage Examples:**

195

196

```java

197

import com.fasterxml.jackson.annotation.*;

198

199

public class AnnotatedPerson {

200

@KVIndex

201

@JsonProperty("person_id") // Custom JSON property name

202

public String id;

203

204

@KVIndex("name")

205

@JsonProperty("full_name")

206

public String name;

207

208

@KVIndex("age")

209

public int age;

210

211

@JsonIgnore // Exclude from serialization

212

public String internalNotes;

213

214

@JsonFormat(pattern = "yyyy-MM-dd") // Custom date format

215

public Date birthDate;

216

217

@JsonInclude(JsonInclude.Include.NON_NULL) // Only include if not null

218

public String nickname;

219

220

// Jackson will use this constructor for deserialization

221

@JsonCreator

222

public AnnotatedPerson(

223

@JsonProperty("person_id") String id,

224

@JsonProperty("full_name") String name,

225

@JsonProperty("age") int age) {

226

this.id = id;

227

this.name = name;

228

this.age = age;

229

}

230

231

// Getters and setters...

232

}

233

234

// The serializer will respect all Jackson annotations

235

KVStore store = new InMemoryStore();

236

AnnotatedPerson person = new AnnotatedPerson("p1", "Alice Johnson", 30);

237

person.nickname = "Al";

238

person.internalNotes = "VIP customer"; // Will be ignored during serialization

239

240

store.write(person); // Serialized using Jackson annotations

241

AnnotatedPerson retrieved = store.read(AnnotatedPerson.class, "p1");

242

// retrieved.internalNotes will be null (was ignored)

243

```

244

245

### Error Handling

246

247

Handle serialization and deserialization errors appropriately.

248

249

**Usage Examples:**

250

251

```java

252

KVStoreSerializer serializer = new KVStoreSerializer();

253

254

try {

255

// Attempt to serialize an object

256

ComplexObject obj = new ComplexObject();

257

byte[] data = serializer.serialize(obj);

258

259

// Attempt to deserialize

260

ComplexObject retrieved = serializer.deserialize(data, ComplexObject.class);

261

262

} catch (JsonProcessingException e) {

263

// Jackson serialization/deserialization error

264

System.err.println("JSON processing failed: " + e.getMessage());

265

} catch (IOException e) {

266

// GZIP compression/decompression error

267

System.err.println("Compression failed: " + e.getMessage());

268

} catch (Exception e) {

269

// Other serialization errors

270

System.err.println("Serialization failed: " + e.getMessage());

271

}

272

```

273

274

### Performance Considerations

275

276

**String vs Object Serialization:**

277

```java

278

KVStoreSerializer serializer = new KVStoreSerializer();

279

280

// Strings are stored as UTF-8 (fast, no compression)

281

String simpleText = "Hello World";

282

byte[] stringData = serializer.serialize(simpleText); // Fast, small overhead

283

284

// Objects are JSON + GZIP compressed (slower, better space efficiency)

285

Person person = new Person("p1", "Alice", 30);

286

byte[] objectData = serializer.serialize(person); // Slower, compressed

287

```

288

289

**Large Object Handling:**

290

```java

291

// For large objects, serialization cost increases

292

LargeDataObject largeObj = new LargeDataObject();

293

largeObj.data = new byte[1024 * 1024]; // 1MB of data

294

295

long start = System.currentTimeMillis();

296

byte[] serialized = serializer.serialize(largeObj);

297

long serializationTime = System.currentTimeMillis() - start;

298

299

System.out.println("Serialization took: " + serializationTime + "ms");

300

System.out.println("Original size: " + largeObj.data.length + " bytes");

301

System.out.println("Compressed size: " + serialized.length + " bytes");

302

System.out.println("Compression ratio: " + (1.0 - (double)serialized.length / largeObj.data.length));

303

```

304

305

### Thread Safety

306

307

The KVStoreSerializer is thread-safe and can be used concurrently.

308

309

**Usage Examples:**

310

311

```java

312

// Single serializer instance can be used by multiple threads

313

KVStoreSerializer sharedSerializer = new KVStoreSerializer();

314

315

// Thread-safe concurrent usage

316

ExecutorService executor = Executors.newFixedThreadPool(10);

317

318

for (int i = 0; i < 100; i++) {

319

final int index = i;

320

executor.submit(() -> {

321

try {

322

Person person = new Person("p" + index, "Name" + index, 20 + index);

323

byte[] data = sharedSerializer.serialize(person); // Thread-safe

324

Person retrieved = sharedSerializer.deserialize(data, Person.class); // Thread-safe

325

} catch (Exception e) {

326

e.printStackTrace();

327

}

328

});

329

}

330

331

executor.shutdown();

332

```