Skip to content

Commit 96a02f4

Browse files
committed
make nullable/collectionValueNullable/omitNull supported in codegen
1 parent 113afc7 commit 96a02f4

19 files changed

Lines changed: 403 additions & 139 deletions

src/main/java/com/jsoniter/annotation/JacksonAnnotationSupport.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,21 @@ public Class<? extends Encoder> encoder() {
8383
return Encoder.class;
8484
}
8585

86+
@Override
87+
public boolean nullable() {
88+
return true;
89+
}
90+
91+
@Override
92+
public boolean collectionValueNullable() {
93+
return true;
94+
}
95+
96+
@Override
97+
public boolean omitNull() {
98+
return true;
99+
}
100+
86101
@Override
87102
public Class<? extends Annotation> annotationType() {
88103
return JsonProperty.class;

src/main/java/com/jsoniter/annotation/JsonObject.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,20 @@
99
@Retention(RetentionPolicy.RUNTIME)
1010
public @interface JsonObject {
1111

12-
// if the unknown property is in this list, it will be treated as extra
13-
// if @JsonExtraProperties not defined, it will be treated as error
12+
/**
13+
* @return if the unknown property is in this list, it will be treated as extra,
14+
* if the unknown property is in this list, it will be treated as extra
15+
*/
1416
String[] unknownPropertiesBlacklist() default {};
1517

16-
// if the unknown property is in this list, it will be silently ignored
18+
/**
19+
* @return if the unknown property is in this list, it will be silently ignored
20+
*/
1721
String[] unknownPropertiesWhitelist() default {};
1822

19-
// if true, all known properties will be treated as extra
20-
// if @JsonExtraProperties not defined, it will be treated as error
23+
/**
24+
* @return if true, all known properties will be treated as extra,
25+
* if @JsonExtraProperties not defined, it will be treated as error
26+
*/
2127
boolean asExtraForUnknownProperties() default false;
2228
}

src/main/java/com/jsoniter/annotation/JsonProperty.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,55 @@
1212
@Retention(RetentionPolicy.RUNTIME)
1313
public @interface JsonProperty {
1414

15+
/**
16+
* @return alternative name for the field/getter/setter/parameter
17+
*/
1518
String value() default "";
1619

20+
/**
21+
* @return when bind from multiple possible names, set this
22+
*/
1723
String[] from() default {};
1824

25+
/**
26+
* @return when one field will write to multiple object fields, set this
27+
*/
1928
String[] to() default {};
2029

30+
/**
31+
* @return used in decoding only, the field must present in the JSON, regardless null or not
32+
*/
2133
boolean required() default false;
2234

35+
/**
36+
* @return set different decoder just for this field
37+
*/
2338
Class<? extends Decoder> decoder() default Decoder.class;
2439

40+
/**
41+
* @return used in decoding only, choose concrete class for interface/abstract type
42+
*/
2543
Class<?> implementation() default Object.class;
2644

45+
/**
46+
* @return set different encoder just for this field
47+
*/
2748
Class<? extends Encoder> encoder() default Encoder.class;
49+
50+
/**
51+
* @return used in encoding only, should check null for this field,
52+
* skip null checking will make encoding faster
53+
*/
54+
boolean nullable() default true;
55+
56+
/**
57+
* @return used in encoding only, should check null for the value, if it is collection,
58+
* skip null checking will make encoding faster
59+
*/
60+
boolean collectionValueNullable() default true;
61+
62+
/**
63+
* @return if true, do not write the field altogether if value is null
64+
*/
65+
boolean omitNull() default true;
2866
}

src/main/java/com/jsoniter/annotation/JsoniterAnnotationSupport.java

Lines changed: 41 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ private void detectUnwrappers(ClassDescriptor desc, List<Method> allMethods) {
6262
if (method.getAnnotation(JsonUnwrapper.class) == null) {
6363
continue;
6464
}
65-
desc.unwrappers.add(method);
65+
desc.unWrappers.add(method);
6666
}
6767
}
6868

@@ -83,10 +83,7 @@ private void detectWrappers(ClassDescriptor desc, List<Method> allMethods) {
8383
Binding binding = new Binding(desc.clazz, desc.lookup, method.getGenericParameterTypes()[i]);
8484
JsonProperty jsonProperty = getJsonProperty(paramAnnotations);
8585
if (jsonProperty != null) {
86-
binding.name = jsonProperty.value();
87-
if (jsonProperty.required()) {
88-
binding.asMissingWhenNotPresent = true;
89-
}
86+
updateBindingWithJsonProperty(binding, jsonProperty);
9087
}
9188
if (binding.name == null || binding.name.length() == 0) {
9289
binding.name = paramNames[i];
@@ -134,10 +131,7 @@ private void detectStaticFactory(ClassDescriptor desc, List<Method> allMethods)
134131
JsonProperty jsonProperty = getJsonProperty(paramAnnotations);
135132
Binding binding = new Binding(desc.clazz, desc.lookup, method.getGenericParameterTypes()[i]);
136133
if (jsonProperty != null) {
137-
binding.name = jsonProperty.value();
138-
if (jsonProperty.required()) {
139-
binding.asMissingWhenNotPresent = true;
140-
}
134+
updateBindingWithJsonProperty(binding, jsonProperty);
141135
}
142136
if (binding.name == null || binding.name.length() == 0) {
143137
binding.name = paramNames[i];
@@ -164,10 +158,7 @@ private void detectCtor(ClassDescriptor desc) {
164158
JsonProperty jsonProperty = getJsonProperty(paramAnnotations);
165159
Binding binding = new Binding(desc.clazz, desc.lookup, ctor.getGenericParameterTypes()[i]);
166160
if (jsonProperty != null) {
167-
binding.name = jsonProperty.value();
168-
if (jsonProperty.required()) {
169-
binding.asMissingWhenNotPresent = true;
170-
}
161+
updateBindingWithJsonProperty(binding, jsonProperty);
171162
}
172163
if (binding.name == null || binding.name.length() == 0) {
173164
binding.name = paramNames[i];
@@ -187,38 +178,7 @@ private void updateBindings(ClassDescriptor desc) {
187178
}
188179
JsonProperty jsonProperty = getJsonProperty(binding.annotations);
189180
if (jsonProperty != null) {
190-
String altName = jsonProperty.value();
191-
if (!altName.isEmpty()) {
192-
binding.name = altName;
193-
binding.fromNames = new String[]{altName};
194-
}
195-
if (jsonProperty.from().length > 0) {
196-
binding.fromNames = jsonProperty.from();
197-
}
198-
if (jsonProperty.to().length > 0) {
199-
binding.toNames = jsonProperty.to();
200-
}
201-
if (jsonProperty.required()) {
202-
binding.asMissingWhenNotPresent = true;
203-
}
204-
if (jsonProperty.decoder() != Decoder.class) {
205-
try {
206-
binding.decoder = jsonProperty.decoder().newInstance();
207-
} catch (Exception e) {
208-
throw new JsonException(e);
209-
}
210-
}
211-
if (jsonProperty.encoder() != Encoder.class) {
212-
try {
213-
binding.encoder = jsonProperty.encoder().newInstance();
214-
} catch (Exception e) {
215-
throw new JsonException(e);
216-
}
217-
}
218-
if (jsonProperty.implementation() != Object.class) {
219-
binding.valueType = ParameterizedTypeImpl.useImpl(binding.valueType, jsonProperty.implementation());
220-
binding.valueTypeLiteral = TypeLiteral.create(binding.valueType);
221-
}
181+
updateBindingWithJsonProperty(binding, jsonProperty);
222182
}
223183
if (getAnnotation(binding.annotations, JsonMissingProperties.class) != null) {
224184
// this binding will not bind from json
@@ -235,6 +195,42 @@ private void updateBindings(ClassDescriptor desc) {
235195
}
236196
}
237197

198+
private void updateBindingWithJsonProperty(Binding binding, JsonProperty jsonProperty) {
199+
binding.asMissingWhenNotPresent = jsonProperty.required();
200+
binding.isNullable = jsonProperty.nullable();
201+
binding.isCollectionValueNullable = jsonProperty.collectionValueNullable();
202+
binding.shouldOmitNull = jsonProperty.omitNull();
203+
String altName = jsonProperty.value();
204+
if (!altName.isEmpty()) {
205+
binding.name = altName;
206+
binding.fromNames = new String[]{altName};
207+
}
208+
if (jsonProperty.from().length > 0) {
209+
binding.fromNames = jsonProperty.from();
210+
}
211+
if (jsonProperty.to().length > 0) {
212+
binding.toNames = jsonProperty.to();
213+
}
214+
if (jsonProperty.decoder() != Decoder.class) {
215+
try {
216+
binding.decoder = jsonProperty.decoder().newInstance();
217+
} catch (Exception e) {
218+
throw new JsonException(e);
219+
}
220+
}
221+
if (jsonProperty.encoder() != Encoder.class) {
222+
try {
223+
binding.encoder = jsonProperty.encoder().newInstance();
224+
} catch (Exception e) {
225+
throw new JsonException(e);
226+
}
227+
}
228+
if (jsonProperty.implementation() != Object.class) {
229+
binding.valueType = ParameterizedTypeImpl.useImpl(binding.valueType, jsonProperty.implementation());
230+
binding.valueTypeLiteral = TypeLiteral.create(binding.valueType);
231+
}
232+
}
233+
238234
protected JsonCreator getJsonCreator(Annotation[] annotations) {
239235
return getAnnotation(annotations, JsonCreator.class);
240236
}

src/main/java/com/jsoniter/output/Codegen.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ private static synchronized Encoder gen(String cacheKey, Type type) {
116116
}
117117
}
118118
clazz = chooseAccessibleSuper(clazz);
119-
CodegenResult source = genSource(clazz, typeArgs);
119+
CodegenResult source = genSource(cacheKey, clazz, typeArgs);
120120
if ("true".equals(System.getenv("JSONITER_DEBUG"))) {
121121
System.out.println(">>> " + cacheKey);
122122
System.out.println("prelude: " + source.prelude);
@@ -191,15 +191,15 @@ private static void createDir(String cacheKey) {
191191
}
192192
}
193193

194-
private static CodegenResult genSource(Class clazz, Type[] typeArgs) {
194+
private static CodegenResult genSource(String cacheKey, Class clazz, Type[] typeArgs) {
195195
if (clazz.isArray()) {
196-
return CodegenImplArray.genArray(clazz);
196+
return CodegenImplArray.genArray(cacheKey, clazz);
197197
}
198198
if (Map.class.isAssignableFrom(clazz)) {
199-
return CodegenImplMap.genMap(clazz, typeArgs);
199+
return CodegenImplMap.genMap(cacheKey, clazz, typeArgs);
200200
}
201201
if (Collection.class.isAssignableFrom(clazz)) {
202-
return CodegenImplArray.genCollection(clazz, typeArgs);
202+
return CodegenImplArray.genCollection(cacheKey, clazz, typeArgs);
203203
}
204204
if (clazz.isEnum()) {
205205
return CodegenImplNative.genEnum(clazz);

src/main/java/com/jsoniter/output/CodegenAccess.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ public static void writeVal(String cacheKey, double obj, JsonStream stream) thro
5252
encoder.encodeDouble(obj, stream);
5353
}
5454

55+
public static void writeStringWithoutQuote(String obj, JsonStream stream) throws IOException {
56+
StreamImplString.writeStringWithoutQuote(stream, obj);
57+
}
58+
5559
public static void staticGenEncoders(TypeLiteral[] typeLiterals) {
5660
Codegen.staticGenEncoders(typeLiterals);
5761
}

0 commit comments

Comments
 (0)