Skip to content

Commit bbab957

Browse files
authored
Merge pull request #86 from MikeDombo/no-static
Add option for serializing and deserializing non-final static fields, disabled by default
2 parents e69b3cc + ecfc4a1 commit bbab957

File tree

6 files changed

+120
-69
lines changed

6 files changed

+120
-69
lines changed

jr-annotation-support/src/main/java/com/fasterxml/jackson/jr/annotationsupport/AnnotationBasedIntrospector.java

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,22 @@ public class AnnotationBasedIntrospector
3131
* Visibility settings to use for auto-detecting accessors.
3232
*/
3333
protected final JsonAutoDetect.Value _visibility;
34-
34+
3535
// // // State (collected properties, related)
36-
36+
3737
protected final Map<String, APropBuilder> _props = new HashMap<String, APropBuilder>();
3838

3939
// // // State only for deserialization:
4040

4141
protected Set<String> _ignorableNames;
42+
protected int _features;
4243

4344
protected AnnotationBasedIntrospector(Class<?> type, boolean serialization,
44-
JsonAutoDetect.Value visibility) {
45+
JsonAutoDetect.Value visibility, int features) {
4546
_type = type;
4647
_forSerialization = serialization;
4748
_ignorableNames = serialization ? null : new HashSet<String>();
49+
_features = features;
4850

4951
// First things first: find possible `@JsonAutoDetect` to override
5052
// default visibility settings
@@ -58,13 +60,13 @@ protected AnnotationBasedIntrospector(Class<?> type, boolean serialization,
5860

5961
public static POJODefinition pojoDefinitionForDeserialization(JSONReader r,
6062
Class<?> pojoType, JsonAutoDetect.Value visibility) {
61-
return new AnnotationBasedIntrospector(pojoType, false, visibility)
63+
return new AnnotationBasedIntrospector(pojoType, false, visibility, r.features())
6264
.introspectDefinition();
6365
}
6466

6567
public static POJODefinition pojoDefinitionForSerialization(JSONWriter w,
6668
Class<?> pojoType, JsonAutoDetect.Value visibility) {
67-
return new AnnotationBasedIntrospector(pojoType, true, visibility)
69+
return new AnnotationBasedIntrospector(pojoType, true, visibility, w.features())
6870
.introspectDefinition();
6971
}
7072

@@ -235,9 +237,9 @@ protected void _findFields(final Class<?> currType)
235237

236238
// then get fields from within class itself
237239
for (Field f : currType.getDeclaredFields()) {
238-
// Does not include static fields, but there are couple of things we do
239-
// not include regardless:
240-
if (f.isEnumConstant() || f.isSynthetic()) {
240+
// skip static fields and synthetic fields except for enum constants
241+
if ((JSON.Feature.INCLUDE_STATIC_FIELDS.isDisabled(_features) && Modifier.isStatic(f.getModifiers())
242+
&& !f.isEnumConstant()) || f.isSynthetic()) {
241243
continue;
242244
}
243245
// otherwise, first things first; explicit ignoral?
@@ -284,7 +286,7 @@ protected void _findMethods(final Class<?> currType)
284286
final int flags = m.getModifiers();
285287
// 13-Jun-2015, tatu: Skip synthetic, bridge methods altogether, for now
286288
// at least (add more complex handling only if absolutely necessary)
287-
if (Modifier.isStatic(flags)
289+
if ((JSON.Feature.INCLUDE_STATIC_FIELDS.isDisabled(_features) && Modifier.isStatic(flags))
288290
|| m.isSynthetic() || m.isBridge()) {
289291
continue;
290292
}
@@ -350,7 +352,7 @@ protected void _checkGetterMethod(Method m)
350352
acc = APropAccessor.createVisible(implName, m);
351353
} else {
352354
acc = APropAccessor.createExplicit(explName, m);
353-
}
355+
}
354356
}
355357
}
356358
_propBuilder(implName).getter = acc;
@@ -397,7 +399,7 @@ protected void _checkSetterMethod(Method m)
397399
acc = APropAccessor.createVisible(implName, m);
398400
} else {
399401
acc = APropAccessor.createExplicit(explName, m);
400-
}
402+
}
401403
}
402404
}
403405
_propBuilder(implName).setter = acc;
@@ -410,9 +412,10 @@ protected void _checkSetterMethod(Method m)
410412
*/
411413

412414
protected boolean _isFieldVisible(Field f) {
413-
// Consider transient to be non-visible
415+
// Consider transient and static-final to be non-visible
414416
// TODO: (maybe?) final
415-
return !Modifier.isTransient(f.getModifiers())
417+
return !(Modifier.isFinal(f.getModifiers()) && Modifier.isStatic(f.getModifiers()))
418+
&& !Modifier.isTransient(f.getModifiers())
416419
&& _visibility.getFieldVisibility().isVisible(f);
417420
}
418421

@@ -426,7 +429,7 @@ protected boolean _isGetterVisible(Method m, boolean isIsGetter) {
426429
protected boolean _isSetterVisible(Method m) {
427430
return _visibility.getSetterVisibility().isVisible(m);
428431
}
429-
432+
430433
/*
431434
/**********************************************************************
432435
/* Internal methods, annotation introspection
@@ -449,7 +452,7 @@ protected String _findExplicitName(AnnotatedElement m) {
449452
* Lookup method for finding possible annotated order of property names
450453
* for the type this introspector is to introspect
451454
*
452-
* @return List of property names that defines order (possibly partial); if
455+
* @return List of property names that defines order (possibly partial); if
453456
* none, empty List (but never null)
454457
*/
455458
protected List<String> _findNameSortOrder() {
@@ -465,7 +468,7 @@ protected List<String> _findNameSortOrder() {
465468
* for the type this introspector is to introspect that should be ignored
466469
* (both for serialization and deserialization).
467470
*
468-
* @return List of property names that defines order (possibly partial); if
471+
* @return List of property names that defines order (possibly partial); if
469472
* none, empty List (but never null)
470473
*/
471474
protected Collection<String> _findIgnorableNames() {
@@ -480,13 +483,13 @@ protected Collection<String> _findIgnorableNames() {
480483
protected <ANN extends Annotation> ANN _find(AnnotatedElement elem, Class<ANN> annotationType) {
481484
return elem.getAnnotation(annotationType);
482485
}
483-
486+
484487
/*
485488
/**********************************************************************
486489
/* Internal methods, other
487490
/**********************************************************************
488491
*/
489-
492+
490493
protected APropBuilder _propBuilder(String name) {
491494
APropBuilder b = _props.get(name);
492495
if (b == null) {
@@ -546,7 +549,7 @@ protected static String _decap(String name) {
546549
/* Helper classes
547550
/**********************************************************************
548551
*/
549-
552+
550553
protected static class APropBuilder
551554
implements Comparable<APropBuilder>
552555
{
@@ -615,7 +618,7 @@ private static <A extends AccessibleObject> APropAccessor<A> _merge(APropAccesso
615618
// should be fine to take first one
616619
return a1;
617620
}
618-
621+
619622
public APropBuilder withName(String newName) {
620623
APropBuilder newB = new APropBuilder(this, newName);
621624
newB.field = field;
@@ -676,7 +679,7 @@ private static Set<String> _collectAliases(APropAccessor<?> acc, Set<String> col
676679
}
677680
return collectedAliases;
678681
}
679-
682+
680683
private String _firstExplicit(APropAccessor<?> acc1,
681684
APropAccessor<?> acc2,
682685
APropAccessor<?> acc3) {

jr-annotation-support/src/test/java/com/fasterxml/jackson/jr/annotationsupport/BasicIgnoralTest.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
public class BasicIgnoralTest extends ASTestBase
88
{
99
static class XY {
10+
public static int DEFAULT = 123;
11+
public static final int DEFAULT_FINAL = 123;
1012
@JsonIgnore
1113
public int x;
1214
public int y;
@@ -42,13 +44,16 @@ public XYZ(int x, int y, int z) {
4244
}
4345

4446
private final JSON JSON_WITH_ANNO = jsonWithAnnotationSupport();
47+
private final JSON JSON_WITH_ANNO_WITH_STATIC =
48+
JSON.builder().register(JacksonAnnotationExtension.std).enable(JSON.Feature.INCLUDE_STATIC_FIELDS).build();
49+
private final JSON JSON_WITH_STATIC = JSON.builder().enable(JSON.Feature.INCLUDE_STATIC_FIELDS).build();
4550

4651
/*
4752
/**********************************************************************
4853
/* Tests for basic @JsonIgnore
4954
/**********************************************************************
5055
*/
51-
56+
5257
public void testPropertyIgnoralOnSerialize() throws Exception
5358
{
5459
final XY input = new XY(1, 2);
@@ -60,26 +65,41 @@ public void testPropertyIgnoralOnSerialize() throws Exception
6065

6166
// and ensure no leakage to default one:
6267
assertEquals(a2q("{'x':1,'y':2}"), JSON.std.asString(input));
68+
69+
// Verify serialization of static fields when the INCLUDE_STATIC_FIELDS option is enabled
70+
assertEquals(a2q("{'DEFAULT':123,'x':1,'y':2}"), JSON_WITH_STATIC.asString(input));
71+
assertEquals(a2q("{'DEFAULT':123,'y':2}"), JSON_WITH_ANNO_WITH_STATIC.asString(input));
6372
}
6473

6574
public void testPropertyIgnoralOnDeserialize() throws Exception
6675
{
67-
final String json = a2q("{'x':1,'y':2}");
76+
final String json = a2q("{'DEFAULT':125,'x':1,'y':2}");
6877

6978
// default: no filtering by ignorals
7079
XY result = JSON.std.beanFrom(XY.class, json);
7180
assertEquals(1, result.x);
7281
assertEquals(2, result.y);
82+
assertEquals(XY.DEFAULT_FINAL, XY.DEFAULT);
7383

7484
// but with ignore, should skip
7585
result = JSON_WITH_ANNO.beanFrom(XY.class, json);
7686
assertEquals(0, result.x);
7787
assertEquals(2, result.y);
88+
assertEquals(XY.DEFAULT_FINAL, XY.DEFAULT);
7889

7990
// and once again verify non-stickiness
8091
result = JSON.std.beanFrom(XY.class, json);
8192
assertEquals(1, result.x);
8293
assertEquals(2, result.y);
94+
assertEquals(XY.DEFAULT_FINAL, XY.DEFAULT);
95+
96+
// Verify setting static field from serialized data when the INCLUDE_STATIC_FIELDS option is enabled
97+
JSON_WITH_STATIC.beanFrom(XY.class, json);
98+
assertEquals(125, XY.DEFAULT);
99+
XY.DEFAULT = XY.DEFAULT_FINAL;
100+
JSON_WITH_ANNO_WITH_STATIC.beanFrom(XY.class, json);
101+
assertEquals(125, XY.DEFAULT);
102+
XY.DEFAULT = XY.DEFAULT_FINAL;
83103
}
84104

85105
public void testPropertyIgnoreWithUnknown() throws Exception

0 commit comments

Comments
 (0)