Skip to content

Commit

Permalink
Fix #296
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed May 14, 2015
1 parent 4a8c637 commit cb6dddd
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 98 deletions.
5 changes: 5 additions & 0 deletions release-notes/CREDITS
Original file line number Diff line number Diff line change
Expand Up @@ -266,3 +266,8 @@ Laird Nelson (ljnelson@github)
Derk Norton (derknorton@github)
* Suggested #689: Add `ObjectMapper.setDefaultPrettyPrinter(PrettyPrinter)`
(2.6.0)

Michal Letynski (mletynski@github)
* Suggested #296: Serialization of transient fields with public getters (add
MapperFeature.PROPAGATE_TRANSIENT_MARKER)
(2.6.0)
3 changes: 3 additions & 0 deletions release-notes/VERSION
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ Project: jackson-databind
2.6.0 (not yet released)

#95: Allow read-only properties with `@JsonIgnoreProperties(allowGetters=true)`
#296: Serialization of transient fields with public getters (add
MapperFeature.PROPAGATE_TRANSIENT_MARKER)
(suggested by Michal L)
#312: Support Type Id mappings where two ids map to same Class
#348: ObjectMapper.valueToTree does not work with @JsonRawValue
(reported by Chris P, pimlottc@github)
Expand Down
15 changes: 13 additions & 2 deletions src/main/java/com/fasterxml/jackson/databind/MapperFeature.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public enum MapperFeature implements ConfigFeature
{
/*
/******************************************************
/* Introspection features
/* Introspection features
/******************************************************
*/

Expand Down Expand Up @@ -198,7 +198,18 @@ public enum MapperFeature implements ConfigFeature
* @since 2.2
*/
ALLOW_FINAL_FIELDS_AS_MUTATORS(true),


/**
* Feature that determines for <code>transient</code> modifier for fields
* is handled: if disabled, it is only taken to mean exclusion of
*<p>
* Feature is disabled by default, meaning that existence of `transient`
* for a field does not necessarily lead to ignoral of getters or setters.
*
* @since 2.6
*/
PROPAGATE_TRANSIENT_MARKER(false),

/*
/******************************************************
/* Type-handling features
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,7 @@ protected Map<String,AnnotatedField> _findFields(Class<?> c, Map<String,Annotate
*/
fields = _findFields(parent, fields);
for (Field f : c.getDeclaredFields()) {
// static fields not included, nor transient
// static fields not included (transients are at this point, filtered out later)
if (!_isIncludableField(f)) {
continue;
}
Expand Down Expand Up @@ -869,9 +869,10 @@ private boolean _isIncludableField(Field f)
if (f.isSynthetic()) {
return false;
}
// Static fields are never included, nor transient
// Static fields are never included. Transient are (since 2.6), for
// purpose of propagating removal
int mods = f.getModifiers();
if (Modifier.isStatic(mods) || Modifier.isTransient(mods)) {
if (Modifier.isStatic(mods)) {
return false;
}
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;

import com.fasterxml.jackson.databind.util.ClassUtil;
Expand Down Expand Up @@ -133,6 +134,11 @@ public String getFullName() {

public int getAnnotationCount() { return _annotations.size(); }

/**
* @since 2.6
*/
public boolean isTransient() { return Modifier.isTransient(getModifiers()); }

@Override
public int hashCode() {
return _field.getName().hashCode();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public class POJOPropertiesCollector

/**
* True if introspection is done for serialization (giving
* precedence for serialization annotations), or not (false, deserialization)
* precedence for serialization annotations), or not (false, deserialization)
*/
protected final boolean _forSerialization;

Expand Down Expand Up @@ -386,13 +386,14 @@ protected void _addFields()
* (although, maybe surprisingly, JVM _can_ force setting of such fields!)
*/
final boolean pruneFinalFields = !_forSerialization && !_config.isEnabled(MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS);
final boolean transientAsIgnoral = _config.isEnabled(MapperFeature.PROPAGATE_TRANSIENT_MARKER);

for (AnnotatedField f : _classDef.fields()) {
String implName = (ai == null) ? null : ai.findImplicitPropertyName(f);
if (implName == null) {
implName = f.getName();
}

PropertyName pn;

if (ai == null) {
Expand Down Expand Up @@ -420,7 +421,15 @@ protected void _addFields()
}
// and finally, may also have explicit ignoral
boolean ignored = (ai != null) && ai.hasIgnoreMarker(f);
/* [Issue#190]: this is the place to prune final fields, if they are not

// 13-May-2015, tatu: Moved from earlier place (AnnotatedClass) in 2.6
if (f.isTransient()) {
visible = false;
if (transientAsIgnoral) {
ignored = true;
}
}
/* [databind#190]: this is the place to prune final fields, if they are not
* to be used as mutators. Must verify they are not explicitly included.
* Also: if 'ignored' is set, need to included until a later point, to
* avoid losing ignoral information.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -582,71 +582,6 @@ private static <T> Linked<T> merge(Linked<T> chain1, Linked<T> chain2)
return chain1.append(chain2);
}

// // Deprecated variants that do not take 'explName': to be removed in a later version
// // (but are used at least by 2.3 and earlier versions of Scala module at least so
// // need to be careful with phasing out if before 3.0)

/**
* @deprecated Since 2.4 call method that takes additional 'explName' argument, to indicate
* whether name of property was provided by annotation (and not derived from accessor name);
* this method assumes the name is explicit if it is non-null.
*/
@Deprecated
public void addField(AnnotatedField a, String name, boolean visible, boolean ignored) {
addField(a, _propName(name), name != null, visible, ignored);
}

@Deprecated
public void addField(AnnotatedField a, String name, boolean explName, boolean visible, boolean ignored) {
addField(a, _propName(name), explName, visible, ignored);
}

/**
* @deprecated Since 2.4 call method that takes additional 'explName' argument, to indicate
* whether name of property was provided by annotation (and not derived from accessor name);
* this method assumes the name is explicit if it is non-null.
*/
@Deprecated
public void addCtor(AnnotatedParameter a, String name, boolean visible, boolean ignored) {
addCtor(a, _propName(name), name != null, visible, ignored);
}
@Deprecated
public void addCtor(AnnotatedParameter a, String name, boolean explName, boolean visible, boolean ignored) {
addCtor(a, _propName(name), explName, visible, ignored);
}

/**
* @deprecated Since 2.4 call method that takes additional 'explName' argument, to indicate
* whether name of property was provided by annotation (and not derived from accessor name);
* this method assumes the name is explicit if it is non-null.
*/
@Deprecated
public void addGetter(AnnotatedMethod a, String name, boolean visible, boolean ignored) {
addGetter(a, _propName(name), name != null, visible, ignored);
}
@Deprecated
public void addGetter(AnnotatedMethod a, String name, boolean explName, boolean visible, boolean ignored) {
addGetter(a, _propName(name), explName, visible, ignored);
}

/**
* @deprecated Since 2.4 call method that takes additional 'explName' argument, to indicate
* whether name of property was provided by annotation (and not derived from accessor name);
* this method assumes the name is explicit if it is non-null.
*/
@Deprecated
public void addSetter(AnnotatedMethod a, String name, boolean visible, boolean ignored) {
addSetter(a, _propName(name), name != null, visible, ignored);
}
@Deprecated
public void addSetter(AnnotatedMethod a, String name, boolean explName, boolean visible, boolean ignored) {
addSetter(a, _propName(name), explName, visible, ignored);
}

private PropertyName _propName(String simple) {
return PropertyName.construct(simple, null);
}

/*
/**********************************************************
/* Modifications
Expand Down Expand Up @@ -831,30 +766,6 @@ private <T> boolean _anyIgnorals(Linked<T> n)
return false;
}

/**
* @since 2.4 Use {@link #findExplicitNames} instead
*/
@Deprecated
public String findNewName()
{
Collection<PropertyName> l = findExplicitNames();
if (l == null) {
return null;
}

// 13-Apr-2014, tatu: Start with code similar to existing conflict checks
if (l.size() > 1) {
throw new IllegalStateException("Conflicting/ambiguous property name definitions (implicit name '"
+_name+"'): found more than one explicit name: "
+l);
}
PropertyName first = l.iterator().next();
if (first.equals(_name)) {
return null;
}
return first.getSimpleName();
}

/**
* Method called to find out set of explicit names for accessors
* bound together due to implicit name.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.fasterxml.jackson.databind.introspect;

import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.databind.*;

// tests for [databind#296]
public class TransientFieldTest extends BaseMapTest
{
@JsonPropertyOrder({ "x" })
static class ClassyTransient
{
public transient int value = 3;

public int getValue() { return value; }

public int getX() { return 42; }
}

public void testTransientFieldHandling() throws Exception
{
// default handling: remove transient field but do not propagate
ObjectMapper m = objectMapper();
assertEquals(aposToQuotes("{'x':42,'value':3}"),
m.writeValueAsString(new ClassyTransient()));

// but may change that
m = new ObjectMapper()
.enable(MapperFeature.PROPAGATE_TRANSIENT_MARKER);
assertEquals(aposToQuotes("{'x':42}"),
m.writeValueAsString(new ClassyTransient()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* Unit tests for verifying that field-backed properties can also be serialized
* (since version 1.1) as well as getter-accessible properties.
*/
public class TestFieldSerialization
public class FieldSerializationTest
extends BaseMapTest
{
/*
Expand Down

0 comments on commit cb6dddd

Please sign in to comment.