Skip to content

Commit 8b26614

Browse files
authoredDec 17, 2016
Update java-extension.md
1 parent c53cf8f commit 8b26614

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed
 

‎java-extension.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,4 +261,100 @@ public static class StaticFactory {
261261

262262
To enable jsoniter annotation support `JsoniterAnnotationSupport.enable()` must be called first
263263

264+
# Setter support
264265

266+
The binding is done in this sequence
267+
268+
```
269+
1. create instance using constructor
270+
2. bind fields
271+
3. call setters
272+
```
273+
274+
By default, methods like `setName(val)` will be caleld with field value from `name`. You can choose to use other kinds of methods as setters. For example
275+
276+
```
277+
public static class WithSetter {
278+
279+
private int field1;
280+
private int field2;
281+
282+
@JsonSetter
283+
public void initialize(@JsonProperty("field1") int field1, @JsonProperty("field2") int field2) {
284+
this.field1 = field1;
285+
this.field2 = field2;
286+
}
287+
}
288+
```
289+
290+
This annotation support is implemented by `Extension` as well. The callback is:
291+
292+
```
293+
public interface Extension {
294+
// ...
295+
List<CustomizedSetter> getSetters(Class clazz);
296+
// ...
297+
}
298+
299+
public class CustomizedSetter {
300+
/**
301+
* which method to call to set value
302+
*/
303+
public String methodName;
304+
305+
/**
306+
* the parameters to bind
307+
*/
308+
public List<Binding> parameters = new ArrayList<Binding>();
309+
}
310+
```
311+
312+
The setter parameters, constructor parameters and fields are all just bindings. Those bindings can be updated by extension, to change data source and decoder.
313+
314+
# Full extension interface
315+
316+
```
317+
public interface Extension {
318+
/**
319+
* Customize type decoding
320+
*
321+
* @param type change how to decode the type
322+
* @param typeArgs for generic type, there might be arguments
323+
* @return null, if no special customization needed
324+
*/
325+
Decoder createDecoder(Type type, Type... typeArgs);
326+
327+
/**
328+
* Customize the binding source or decoder
329+
*
330+
* @param field binding information
331+
* @return true, if stops other extension from customizing same field
332+
*/
333+
boolean updateBinding(Binding field);
334+
335+
/**
336+
* Customize which constructor to call
337+
*
338+
* @param clazz the class of instance to create
339+
* @return null, if fallback to default behavior
340+
*/
341+
CustomizedConstructor getConstructor(Class clazz);
342+
343+
/**
344+
* Customize setters to call after instance is created and fields set
345+
*
346+
* @param clazz the class that is binding
347+
* @return null, if fallback to default behavior
348+
*/
349+
List<CustomizedSetter> getSetters(Class clazz);
350+
}
351+
```
352+
353+
To summary it up, you have these options:
354+
355+
* control how to decode one type, include generic type with different type arguments
356+
* the constructor to use, and the parameter binding of constructor
357+
* the setters to use, and the parameter binding of setters
358+
* all bindings (fields, setter parameters, constructor parameters) can change data source (even map to multiple fields) and change decoder
359+
360+
Also the decoder interface is powered with iterator-api to iterate on the lowest level. I believe all the flexibility you will ever need

0 commit comments

Comments
 (0)