0
# Serialization Schemes
1
2
Serialization schemes control how Thrift objects are encoded and decoded using different strategies. The scheme system provides pluggable serialization implementations that can optimize for different use cases like memory efficiency or compatibility.
3
4
## Capabilities
5
6
### Scheme Interface
7
8
Core interface that all serialization schemes implement.
9
10
```java { .api }
11
/**
12
* Interface for serialization schemes that control how Thrift objects are encoded/decoded
13
* @param <T> The TBase type this scheme handles
14
*/
15
public interface IScheme<T extends TBase> {
16
/** Read (deserialize) a Thrift object from protocol */
17
public void read(TProtocol iproto, T struct) throws TException;
18
19
/** Write (serialize) a Thrift object to protocol */
20
public void write(TProtocol oproto, T struct) throws TException;
21
}
22
23
/**
24
* Factory interface for creating scheme instances
25
*/
26
public interface SchemeFactory {
27
/** Create a new scheme instance for the given type */
28
public IScheme getScheme();
29
}
30
```
31
32
### Standard Scheme
33
34
Default serialization scheme used by most generated Thrift classes.
35
36
```java { .api }
37
/**
38
* Standard serialization scheme that reads/writes all fields with full metadata
39
*/
40
public class StandardScheme<T extends TBase> implements IScheme<T> {
41
/** Read object from protocol using standard field-by-field approach */
42
public void read(TProtocol iproto, T struct) throws TException;
43
44
/** Write object to protocol using standard field-by-field approach */
45
public void write(TProtocol oproto, T struct) throws TException;
46
}
47
```
48
49
**Usage Examples:**
50
51
```java
52
import org.apache.thrift.scheme.StandardScheme;
53
import org.apache.thrift.scheme.IScheme;
54
55
// Standard scheme is typically used automatically by generated code
56
public class MyStruct implements TBase<MyStruct, MyStruct._Fields> {
57
private static final IScheme<MyStruct> STANDARD_SCHEME = new StandardScheme<MyStruct>();
58
59
// Generated read method
60
public void read(TProtocol iprot) throws TException {
61
STANDARD_SCHEME.read(iprot, this);
62
}
63
64
// Generated write method
65
public void write(TProtocol oprot) throws TException {
66
STANDARD_SCHEME.write(oprot, this);
67
}
68
}
69
```
70
71
### Tuple Scheme
72
73
Memory-efficient serialization scheme that omits field metadata for smaller payloads.
74
75
```java { .api }
76
/**
77
* Tuple-based serialization scheme for memory efficiency
78
* Serializes fields in order without field IDs or names
79
*/
80
public class TupleScheme<T extends TBase> implements IScheme<T> {
81
/** Read object from protocol using tuple approach (no field metadata) */
82
public void read(TProtocol iproto, T struct) throws TException;
83
84
/** Write object to protocol using tuple approach (no field metadata) */
85
public void write(TProtocol oproto, T struct) throws TException;
86
}
87
```
88
89
**Usage Examples:**
90
91
```java
92
import org.apache.thrift.scheme.TupleScheme;
93
import org.apache.thrift.protocol.TTupleProtocol;
94
95
// Tuple scheme is often used with TTupleProtocol for efficiency
96
public class MyStruct implements TBase<MyStruct, MyStruct._Fields> {
97
private static final IScheme<MyStruct> TUPLE_SCHEME = new TupleScheme<MyStruct>();
98
99
// Use tuple scheme for efficient serialization
100
public void write(TTupleProtocol oprot) throws TException {
101
TUPLE_SCHEME.write(oprot, this);
102
}
103
104
public void read(TTupleProtocol iprot) throws TException {
105
TUPLE_SCHEME.read(iprot, this);
106
}
107
}
108
```
109
110
### Scheme Selection
111
112
Generated Thrift classes typically support both schemes and select based on the protocol type.
113
114
```java
115
// Example of scheme selection in generated code
116
public class MyStruct implements TBase<MyStruct, MyStruct._Fields> {
117
private static final IScheme<MyStruct> STANDARD_SCHEME = new StandardScheme<MyStruct>();
118
private static final IScheme<MyStruct> TUPLE_SCHEME = new TupleScheme<MyStruct>();
119
120
public void read(TProtocol iprot) throws TException {
121
IScheme<MyStruct> scheme = getScheme(iprot);
122
scheme.read(iprot, this);
123
}
124
125
public void write(TProtocol oprot) throws TException {
126
IScheme<MyStruct> scheme = getScheme(oprot);
127
scheme.write(oprot, this);
128
}
129
130
private IScheme<MyStruct> getScheme(TProtocol proto) {
131
return (proto instanceof TTupleProtocol) ? TUPLE_SCHEME : STANDARD_SCHEME;
132
}
133
}
134
```
135
136
### Scheme Factory Pattern
137
138
Factories enable dynamic scheme creation and configuration.
139
140
```java { .api }
141
/**
142
* Example scheme factory implementation
143
*/
144
public class MyStructSchemeFactory implements SchemeFactory {
145
public StandardScheme<MyStruct> getScheme() {
146
return new StandardScheme<MyStruct>();
147
}
148
}
149
150
/**
151
* Tuple scheme factory implementation
152
*/
153
public class MyStructTupleSchemeFactory implements SchemeFactory {
154
public TupleScheme<MyStruct> getScheme() {
155
return new TupleScheme<MyStruct>();
156
}
157
}
158
```
159
160
**Usage Examples:**
161
162
```java
163
import org.apache.thrift.scheme.SchemeFactory;
164
165
// Using scheme factories in generated code
166
public class MyStruct implements TBase<MyStruct, MyStruct._Fields> {
167
private static final Map<Class<? extends IScheme>, SchemeFactory> schemes =
168
new HashMap<Class<? extends IScheme>, SchemeFactory>();
169
170
static {
171
schemes.put(StandardScheme.class, new MyStructSchemeFactory());
172
schemes.put(TupleScheme.class, new MyStructTupleSchemeFactory());
173
}
174
175
public static SchemeFactory getSchemeFactory(Class<? extends IScheme> schemeClass) {
176
return schemes.get(schemeClass);
177
}
178
}
179
```
180
181
### Integration with Protocols
182
183
Different protocols may prefer different schemes for optimal performance.
184
185
```java
186
import org.apache.thrift.protocol.TBinaryProtocol;
187
import org.apache.thrift.protocol.TTupleProtocol;
188
import org.apache.thrift.transport.TMemoryBuffer;
189
190
// Example showing scheme selection based on protocol
191
public class SchemeExample {
192
public void demonstrateSchemes() throws TException {
193
MyStruct obj = new MyStruct();
194
obj.setName("example");
195
obj.setValue(42);
196
197
// Standard scheme with binary protocol
198
TMemoryBuffer buffer1 = new TMemoryBuffer(1024);
199
TBinaryProtocol binaryProto = new TBinaryProtocol(buffer1);
200
obj.write(binaryProto); // Uses StandardScheme automatically
201
202
// Tuple scheme with tuple protocol (more compact)
203
TMemoryBuffer buffer2 = new TMemoryBuffer(1024);
204
TTupleProtocol tupleProto = new TTupleProtocol(buffer2);
205
obj.write(tupleProto); // Uses TupleScheme automatically
206
207
// Tuple serialization is typically more compact
208
System.out.println("Binary protocol size: " + buffer1.length());
209
System.out.println("Tuple protocol size: " + buffer2.length());
210
}
211
}
212
```
213
214
### Custom Scheme Implementation
215
216
Advanced users can implement custom schemes for specialized serialization needs.
217
218
```java
219
import org.apache.thrift.scheme.IScheme;
220
import org.apache.thrift.protocol.TProtocol;
221
222
// Example custom scheme that adds compression
223
public class CompressedScheme<T extends TBase> implements IScheme<T> {
224
private final IScheme<T> delegate;
225
226
public CompressedScheme(IScheme<T> delegate) {
227
this.delegate = delegate;
228
}
229
230
public void read(TProtocol iproto, T struct) throws TException {
231
// Add decompression logic here
232
// Then delegate to standard scheme
233
delegate.read(iproto, struct);
234
}
235
236
public void write(TProtocol oproto, T struct) throws TException {
237
// Delegate to standard scheme
238
delegate.write(oproto, struct);
239
// Add compression logic here
240
}
241
}
242
243
// Custom scheme factory
244
public class CompressedSchemeFactory implements SchemeFactory {
245
private final SchemeFactory delegateFactory;
246
247
public CompressedSchemeFactory(SchemeFactory delegateFactory) {
248
this.delegateFactory = delegateFactory;
249
}
250
251
public IScheme getScheme() {
252
return new CompressedScheme<>(delegateFactory.getScheme());
253
}
254
}
255
```
256
257
## Integration with Generated Code
258
259
Thrift code generators automatically create scheme support in generated classes:
260
261
```java
262
// Typical generated class structure with scheme support
263
public class GeneratedStruct implements TBase<GeneratedStruct, GeneratedStruct._Fields> {
264
// Scheme instances
265
private static final IScheme<GeneratedStruct> STANDARD_SCHEME = new StandardScheme<GeneratedStruct>();
266
private static final IScheme<GeneratedStruct> TUPLE_SCHEME = new TupleScheme<GeneratedStruct>();
267
268
// Scheme selection based on protocol
269
private IScheme<GeneratedStruct> getScheme(TProtocol proto) {
270
return (proto instanceof TTupleProtocol) ? TUPLE_SCHEME : STANDARD_SCHEME;
271
}
272
273
// TBase implementation using schemes
274
public void read(TProtocol iprot) throws TException {
275
getScheme(iprot).read(iprot, this);
276
}
277
278
public void write(TProtocol oprot) throws TException {
279
getScheme(oprot).write(oprot, this);
280
}
281
}
282
```
283
284
Schemes provide a powerful abstraction that allows Thrift objects to be serialized efficiently with different strategies while maintaining a consistent API. The choice between StandardScheme and TupleScheme typically depends on whether you need full field metadata (StandardScheme) or prefer compact serialization (TupleScheme).