First working version of prefix-for-unwrapped; may want to generalize to allow other kinds of name mangling strategies
diff --git a/src/main/java/com/fasterxml/jackson/databind/AnnotationIntrospector.java b/src/main/java/com/fasterxml/jackson/databind/AnnotationIntrospector.java
index 4fa9278..503c5c9 100644
--- a/src/main/java/com/fasterxml/jackson/databind/AnnotationIntrospector.java
+++ b/src/main/java/com/fasterxml/jackson/databind/AnnotationIntrospector.java
@@ -334,9 +334,12 @@
     /**
      * Method called to check whether given property is marked to be "unwrapped"
      * when being serialized (and appropriately handled in reverse direction,
-     * i.e. expect unwrapped representation during deserialization)
+     * i.e. expect unwrapped representation during deserialization).
+     * Return value is the prefix to use for properties (empty String
+     * meaning no prefix), if not null; or null to indicate that no
+     * unwrapping is expected.
      */
-    public Boolean shouldUnwrapProperty(AnnotatedMember member) {
+    public String findUnwrapPrefix(AnnotatedMember member) {
         return null;
     }
 
@@ -347,8 +350,7 @@
      * annotations from multiple accessors (getters, setters, fields,
      * constructor parameters).
      */
-    public boolean hasIgnoreMarker(AnnotatedMember m)
-    {
+    public boolean hasIgnoreMarker(AnnotatedMember m) {
         return false;
     }
 
@@ -970,11 +972,11 @@
         }
 
         @Override        
-        public Boolean shouldUnwrapProperty(AnnotatedMember member)
+        public String findUnwrapPrefix(AnnotatedMember member)
         {
-            Boolean value = _primary.shouldUnwrapProperty(member);
+            String value = _primary.findUnwrapPrefix(member);
             if (value == null) {
-                value = _secondary.shouldUnwrapProperty(member);
+                value = _secondary.findUnwrapPrefix(member);
             }
             return value;
         }
diff --git a/src/main/java/com/fasterxml/jackson/databind/JsonDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/JsonDeserializer.java
index f770e14..9730676 100644
--- a/src/main/java/com/fasterxml/jackson/databind/JsonDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/JsonDeserializer.java
@@ -103,7 +103,7 @@
      * Default implementation just returns 'this'
      * indicating that no unwrapped variant exists
      */
-    public JsonDeserializer<T> unwrappingDeserializer() {
+    public JsonDeserializer<T> unwrappingDeserializer(String prefix) {
         return this;
     }
     
diff --git a/src/main/java/com/fasterxml/jackson/databind/JsonSerializer.java b/src/main/java/com/fasterxml/jackson/databind/JsonSerializer.java
index 8e896a1..96df3ed 100644
--- a/src/main/java/com/fasterxml/jackson/databind/JsonSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/JsonSerializer.java
@@ -33,8 +33,10 @@
      *<p>
      * Default implementation just returns serializer as-is,
      * indicating that no unwrapped variant exists
+     * 
+     * @param prefix Prefix to use for embedded properties, if any
      */
-    public JsonSerializer<T> unwrappingSerializer() {
+    public JsonSerializer<T> unwrappingSerializer(String prefix) {
         return this;
     }
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java
index 3103fc2..ddc2cf9 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java
@@ -215,6 +215,29 @@
     protected BeanDeserializer(BeanDeserializer src, boolean ignoreAllUnknown)
     {
         super(src._beanType);
+        
+        _forClass = src._forClass;
+        _beanType = src._beanType;
+        _property = src._property;
+        
+        _valueInstantiator = src._valueInstantiator;
+        _delegateDeserializer = src._delegateDeserializer;
+        _propertyBasedCreator = src._propertyBasedCreator;
+        
+        _beanProperties = src._beanProperties;
+        _backRefs = src._backRefs;
+        _ignorableProps = src._ignorableProps;
+        _ignoreAllUnknown = ignoreAllUnknown;
+        _anySetter = src._anySetter;
+        _injectables = src._injectables;
+        
+        _nonStandardCreation = src._nonStandardCreation;
+        _unwrappedPropertyHandler = src._unwrappedPropertyHandler;
+    }
+    
+    protected BeanDeserializer(BeanDeserializer src, String unwrapPrefix)
+    {
+        super(src._beanType);
     
         _forClass = src._forClass;
         _beanType = src._beanType;
@@ -224,10 +247,11 @@
         _delegateDeserializer = src._delegateDeserializer;
         _propertyBasedCreator = src._propertyBasedCreator;
 
-        _beanProperties = src._beanProperties;
+        _beanProperties = src._beanProperties.withPrefix(unwrapPrefix);
+
         _backRefs = src._backRefs;
         _ignorableProps = src._ignorableProps;
-        _ignoreAllUnknown = ignoreAllUnknown;
+        _ignoreAllUnknown = (unwrapPrefix != null) || src._ignoreAllUnknown;
         _anySetter = src._anySetter;
         _injectables = src._injectables;
 
@@ -236,7 +260,7 @@
     }
 
     @Override
-    public JsonDeserializer<Object> unwrappingDeserializer()
+    public JsonDeserializer<Object> unwrappingDeserializer(String prefix)
     {
         /* bit kludgy but we don't want to accidentally change type;
          * sub-classes MUST override this method to support unwrapped
@@ -249,7 +273,7 @@
          * properties; since there may be multiple unwrapped values
          * and properties for all may be interleaved...
          */
-        return new BeanDeserializer(this, true);
+        return new BeanDeserializer(this, prefix);
     }
     
     /*
@@ -409,8 +433,6 @@
     /**
      * Helper method called to see if given property is part of 'managed' property
      * pair (managed + back reference), and if so, handle resolution details.
-     * 
-     * @since 1.9
      */
     protected SettableBeanProperty _resolveManagedReferenceProperty(DeserializationConfig config,
             SettableBeanProperty prop)
@@ -459,19 +481,20 @@
     /**
      * Helper method called to see if given property might be so-called unwrapped
      * property: these require special handling.
-     * 
-     * @since 1.9
      */
     protected SettableBeanProperty _resolveUnwrappedProperty(DeserializationConfig config,
             SettableBeanProperty prop)
     {
         AnnotatedMember am = prop.getMember();
-        if (am != null && config.getAnnotationIntrospector().shouldUnwrapProperty(am) == Boolean.TRUE) {
-            JsonDeserializer<Object> orig = prop.getValueDeserializer();
-            JsonDeserializer<Object> unwrapping = orig.unwrappingDeserializer();
-            if (unwrapping != orig && unwrapping != null) {
-                // might be cleaner to create new instance; but difficult to do reliably, so:
-                return prop.withValueDeserializer(unwrapping);
+        if (am != null) {
+            String prefix = config.getAnnotationIntrospector().findUnwrapPrefix(am);
+            if (prefix != null) {
+                JsonDeserializer<Object> orig = prop.getValueDeserializer();
+                JsonDeserializer<Object> unwrapping = orig.unwrappingDeserializer(prefix);
+                if (unwrapping != orig && unwrapping != null) {
+                    // might be cleaner to create new instance; but difficult to do reliably, so:
+                    return prop.withValueDeserializer(unwrapping);
+                }
             }
         }
         return null;
@@ -480,8 +503,6 @@
     /**
      * Helper method that will handle gruesome details of dealing with properties
      * that have non-static inner class as value...
-     * 
-     * @since 1.9
      */
     protected SettableBeanProperty _resolveInnerClassValuedProperty(DeserializationConfig config,
             SettableBeanProperty prop)
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/CreatorProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/CreatorProperty.java
index c279e31..3ff06f0 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/CreatorProperty.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/CreatorProperty.java
@@ -62,11 +62,22 @@
         _injectableValueId = injectableValueId;
     }
 
+    protected CreatorProperty(CreatorProperty src, String newName) {
+        super(src, newName);
+        _annotated = src._annotated;
+        _injectableValueId = src._injectableValueId;
+    }
+    
     protected CreatorProperty(CreatorProperty src, JsonDeserializer<Object> deser) {
         super(src, deser);
         _annotated = src._annotated;
         _injectableValueId = src._injectableValueId;
     }
+
+    @Override
+    public CreatorProperty withName(String newName) {
+        return new CreatorProperty(this, newName);
+    }
     
     @Override
     public CreatorProperty withValueDeserializer(JsonDeserializer<Object> deser) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/SettableBeanProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/SettableBeanProperty.java
index b6f1002..b3a73dd 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/SettableBeanProperty.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/SettableBeanProperty.java
@@ -58,8 +58,6 @@
      * Object used to figure out value to be used when 'null' literal is encountered in JSON.
      * For most types simply Java null, but for primitive types must
      * be a non-null value (like Integer.valueOf(0) for int).
-     * 
-     * @since 1.7
      */
     protected NullProvider _nullProvider;
 
@@ -75,8 +73,6 @@
      * when all properties have been collected. Order of entries
      * is arbitrary, but once indexes are assigned they are not
      * changed.
-     * 
-     * @since 1.7
      */
     protected int _propertyIndex = -1;
     
@@ -105,8 +101,6 @@
 
     /**
      * Basic copy-constructor for sub-classes to use.
-     * 
-     * @since 1.9
      */
     protected SettableBeanProperty(SettableBeanProperty src)
     {
@@ -122,8 +116,6 @@
 
     /**
      * Copy-with-deserializer-change constructor for sub-classes to use.
-     * 
-     * @since 1.9
      */
     protected SettableBeanProperty(SettableBeanProperty src, JsonDeserializer<Object> deser)
     {
@@ -143,7 +135,24 @@
         }
     }
 
+    /**
+     * Copy-with-deserializer-change constructor for sub-classes to use.
+     */
+    protected SettableBeanProperty(SettableBeanProperty src, String newName)
+    {
+        _propName = newName;
+        _type = src._type;
+        _contextAnnotations = src._contextAnnotations;
+        _valueDeserializer = src._valueDeserializer;
+        _valueTypeDeserializer = src._valueTypeDeserializer;
+        _nullProvider = src._nullProvider;
+        _managedReferenceName = src._managedReferenceName;
+        _propertyIndex = src._propertyIndex;
+    }
+    
     public abstract SettableBeanProperty withValueDeserializer(JsonDeserializer<Object> deser);
+
+    public abstract SettableBeanProperty withName(String newName);
     
     public void setManagedReferenceName(String n) {
         _managedReferenceName = n;
@@ -340,6 +349,17 @@
             _annotated = src._annotated;
             _setter = src._setter;
         }
+
+        protected MethodProperty(MethodProperty src, String newName) {
+            super(src, newName);
+            _annotated = src._annotated;
+            _setter = src._setter;
+        }
+
+        @Override
+        public MethodProperty withName(String newName) {
+            return new MethodProperty(this, newName);
+        }
         
         @Override
         public MethodProperty withValueDeserializer(JsonDeserializer<Object> deser) {
@@ -413,6 +433,17 @@
             _annotated = src._annotated;
             _getter = src._getter;
         }
+
+        protected SetterlessProperty(SetterlessProperty src, String newName) {
+            super(src, newName);
+            _annotated = src._annotated;
+            _getter = src._getter;
+        }
+
+        @Override
+        public SetterlessProperty withName(String newName) {
+            return new SetterlessProperty(this, newName);
+        }
         
         @Override
         public SetterlessProperty withValueDeserializer(JsonDeserializer<Object> deser) {
@@ -505,6 +536,17 @@
             _annotated = src._annotated;
             _field = src._field;
         }
+
+        protected FieldProperty(FieldProperty src, String newName) {
+            super(src, newName);
+            _annotated = src._annotated;
+            _field = src._field;
+        }
+
+        @Override
+        public FieldProperty withName(String newName) {
+            return new FieldProperty(this, newName);
+        }
         
         @Override
         public FieldProperty withValueDeserializer(JsonDeserializer<Object> deser) {
@@ -593,6 +635,19 @@
             _managedProperty = src._managedProperty;
             _backProperty = src._backProperty;
         }
+
+        protected ManagedReferenceProperty(ManagedReferenceProperty src, String newName) {
+            super(src, newName);
+            _referenceName = src._referenceName;
+            _isContainer = src._isContainer;
+            _managedProperty = src._managedProperty;
+            _backProperty = src._backProperty;
+        }
+
+        @Override
+        public ManagedReferenceProperty withName(String newName) {
+            return new ManagedReferenceProperty(this, newName);
+        }
         
         @Override
         public ManagedReferenceProperty withValueDeserializer(JsonDeserializer<Object> deser) {
@@ -670,8 +725,6 @@
      * non-static inner class. If so, we will have to use a special
      * alternative for default constructor; but otherwise can delegate
      * to regular implementation.
-     * 
-     * @since 1.9
      */
     public final static class InnerClassProperty
         extends SettableBeanProperty
@@ -700,7 +753,18 @@
             _delegate = src._delegate.withValueDeserializer(deser);
             _creator = src._creator;
         }
-        
+
+        protected InnerClassProperty(InnerClassProperty src, String newName) {
+            super(src, newName);
+            _delegate = src._delegate.withName(newName);
+            _creator = src._creator;
+        }
+
+        @Override
+        public InnerClassProperty withName(String newName) {
+            return new InnerClassProperty(this, newName);
+        }
+
         @Override
         public InnerClassProperty withValueDeserializer(JsonDeserializer<Object> deser) {
             return new InnerClassProperty(this, deser);
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/BeanPropertyMap.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/BeanPropertyMap.java
index 8204ce6..e16a311 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/BeanPropertyMap.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/BeanPropertyMap.java
@@ -12,8 +12,6 @@
  * is performance: although default implementation is very good for generic
  * use cases, it can still be streamlined a bit for specific use case
  * we have.
- * 
- * @since 1.7
  */
 public final class BeanPropertyMap
 {
@@ -37,7 +35,26 @@
         _buckets = buckets;
     }
 
-    public void assignIndexes()
+    /**
+     * Factory method for constructing a map where all entries use given
+     * prefix
+     */
+    public BeanPropertyMap withPrefix(String prefix)
+    {
+        if (prefix == null || prefix.length() == 0) {
+            return this;
+        }
+        Iterator<SettableBeanProperty> it = allProperties();
+        ArrayList<SettableBeanProperty> newProps = new ArrayList<SettableBeanProperty>();
+        while (it.hasNext()) {
+            SettableBeanProperty prop = it.next();
+            newProps.add(prop.withName(prefix + prop.getName()));
+        }
+        // should we try to re-index? Ordering probably changed but called probably doesn't want changes...
+        return new BeanPropertyMap(newProps);
+    }
+    
+    public BeanPropertyMap assignIndexes()
     {
         // order is arbitrary, but stable:
         int index = 0;
@@ -47,6 +64,7 @@
                 bucket = bucket.next;
             }
         }
+        return this;
     }
     
     private final static int findSize(int size)
@@ -134,8 +152,6 @@
     /**
      * Specialized method for removing specified existing entry.
      * NOTE: entry MUST exist, otherwise an exception is thrown.
-     * 
-     * @since 1.9
      */
     public void remove(SettableBeanProperty property)
     {
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/ThrowableDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/ThrowableDeserializer.java
index 0ad29ea..dddfffb 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/ThrowableDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/ThrowableDeserializer.java
@@ -34,13 +34,13 @@
     /**
      * Alternative constructor used when creating "unwrapping" deserializers
      */
-    protected ThrowableDeserializer(BeanDeserializer src, boolean ignoreAllUnknown)
+    protected ThrowableDeserializer(BeanDeserializer src, String unwrapPrefix)
     {
-        super(src, ignoreAllUnknown);
+        super(src, unwrapPrefix);
     }
     
     @Override
-    public JsonDeserializer<Object> unwrappingDeserializer()
+    public JsonDeserializer<Object> unwrappingDeserializer(String prefix)
     {
         if (getClass() != ThrowableDeserializer.class) {
             return this;
@@ -49,7 +49,7 @@
          * properties; since there may be multiple unwrapped values
          * and properties for all may be interleaved...
          */
-        return new ThrowableDeserializer(this, true);
+        return new ThrowableDeserializer(this, prefix);
     }
 
     
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java b/src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java
index 9d1cb0f..e287ef3 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java
@@ -135,12 +135,15 @@
     }
 
     @Override
-    public Boolean shouldUnwrapProperty(AnnotatedMember member)
+    public String findUnwrapPrefix(AnnotatedMember member)
     {
         JsonUnwrapped ann = member.getAnnotation(JsonUnwrapped.class);
         // if not enabled, just means annotation is not enabled; not necessarily
         // that unwrapping should not be done (relevant when using chained introspectors)
-        return (ann != null && ann.enabled()) ? Boolean.TRUE : null;
+        if (ann != null && ann.enabled()) {
+            return ann.prefix();
+        }
+        return null;
     }
 
     @Override
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/BeanPropertyWriter.java b/src/main/java/com/fasterxml/jackson/databind/ser/BeanPropertyWriter.java
index ae92a4c..ba1a5aa 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/BeanPropertyWriter.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/BeanPropertyWriter.java
@@ -194,8 +194,14 @@
     /**
      * "Copy constructor" to be used by filtering sub-classes
      */
-    protected BeanPropertyWriter(BeanPropertyWriter base)
+    protected BeanPropertyWriter(BeanPropertyWriter base) {
+        this(base, base._name);
+    }
+
+    protected BeanPropertyWriter(BeanPropertyWriter base, SerializedString name)
     {
+        _name = name;
+
         _member = base._member;
         _contextAnnotations = base._contextAnnotations;
         _declaredType = base._declaredType;
@@ -207,7 +213,6 @@
         if (base._internalSettings != null) {
             _internalSettings = new HashMap<Object,Object>(base._internalSettings);
         }
-        _name = base._name;
         _cfgSerializationType = base._cfgSerializationType;
         _dynamicSerializers = base._dynamicSerializers;
         _suppressNulls = base._suppressNulls;
@@ -216,7 +221,14 @@
         _typeSerializer = base._typeSerializer;
         _nonTrivialBaseType = base._nonTrivialBaseType;
     }
-
+    
+    public BeanPropertyWriter withName(String newName) {
+        if (newName.equals(_name.toString())) {
+            return this;
+        }
+        return new BeanPropertyWriter(this, new SerializedString(newName));
+    }
+    
     /**
      * Method called to assign value serializer for property
      * 
@@ -249,8 +261,8 @@
      * Method called create an instance that handles details of unwrapping
      * contained value.
      */
-    public BeanPropertyWriter unwrappingWriter() {
-        return new UnwrappingBeanPropertyWriter(this);
+    public BeanPropertyWriter unwrappingWriter(String prefix) {
+        return new UnwrappingBeanPropertyWriter(this, prefix);
     }
     
     /**
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializer.java
index 212b8d1..df13e00 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializer.java
@@ -79,8 +79,8 @@
     }
 
     @Override
-    public JsonSerializer<Object> unwrappingSerializer() {
-        return new UnwrappingBeanSerializer(this);
+    public JsonSerializer<Object> unwrappingSerializer(String prefix) {
+        return new UnwrappingBeanSerializer(this, prefix);
     }
     
     /*
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/FilteredBeanPropertyWriter.java b/src/main/java/com/fasterxml/jackson/databind/ser/FilteredBeanPropertyWriter.java
index 2cbd21d..f58e2be 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/FilteredBeanPropertyWriter.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/FilteredBeanPropertyWriter.java
@@ -4,7 +4,6 @@
 import com.fasterxml.jackson.databind.JsonSerializer;
 import com.fasterxml.jackson.databind.SerializerProvider;
 
-
 /**
  * Decorated {@link BeanPropertyWriter} that will filter out properties
  * that are not to be included in currently active JsonView.
@@ -40,6 +39,11 @@
         }
 
         @Override
+        public SingleView withName(String newName) {
+            return new SingleView(_delegate.withName(newName), _view);
+        }
+        
+        @Override
         public void assignSerializer(JsonSerializer<Object> ser) {
             _delegate.assignSerializer(ser);
         }
@@ -72,6 +76,11 @@
             _delegate = delegate;
             _views = views;
         }
+
+        @Override
+        public MultiView withName(String newName) {
+            return new MultiView(_delegate.withName(newName), _views);
+        }
         
         @Override
         public void assignSerializer(JsonSerializer<Object> ser) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/PropertyBuilder.java b/src/main/java/com/fasterxml/jackson/databind/ser/PropertyBuilder.java
index eddb195..7a578a8 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/PropertyBuilder.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/PropertyBuilder.java
@@ -136,9 +136,9 @@
                 ser, typeSer, serializationType, m, f, suppressNulls, valueToSuppress);
         
         // [JACKSON-132]: Unwrapping
-        Boolean unwrapped = _annotationIntrospector.shouldUnwrapProperty(am);
-        if (unwrapped != null && unwrapped.booleanValue()) {
-            bpw = bpw.unwrappingWriter();
+        String unwrapPrefix = _annotationIntrospector.findUnwrapPrefix(am);
+        if (unwrapPrefix != null) {
+            bpw = bpw.unwrappingWriter(unwrapPrefix);
         }
         return bpw;
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnwrappingBeanPropertyWriter.java b/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnwrappingBeanPropertyWriter.java
index dab06fa..feeb2b8 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnwrappingBeanPropertyWriter.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnwrappingBeanPropertyWriter.java
@@ -1,13 +1,13 @@
 package com.fasterxml.jackson.databind.ser.impl;
 
 import com.fasterxml.jackson.core.*;
+import com.fasterxml.jackson.core.io.SerializedString;
 import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.JsonMappingException;
 import com.fasterxml.jackson.databind.JsonSerializer;
 import com.fasterxml.jackson.databind.SerializerProvider;
 import com.fasterxml.jackson.databind.ser.*;
 
-
 /**
  * Variant of {@link BeanPropertyWriter} which will handle unwrapping
  * of JSON Object (including of properties of Object within surrounding
@@ -16,8 +16,24 @@
 public class UnwrappingBeanPropertyWriter
     extends BeanPropertyWriter
 {
-    public UnwrappingBeanPropertyWriter(BeanPropertyWriter base) {
+    protected final String _prefix;
+    
+    public UnwrappingBeanPropertyWriter(BeanPropertyWriter base, String prefix) {
         super(base);
+        _prefix = (prefix == null || prefix.length() == 0) ? null : prefix;
+    }
+
+    private UnwrappingBeanPropertyWriter(UnwrappingBeanPropertyWriter base, SerializedString name) {
+        super(base);
+        _prefix = base._prefix;
+    }
+
+    @Override
+    public UnwrappingBeanPropertyWriter withName(String newName) {
+        if (newName.equals(_name.toString())) {
+            return this;
+        }
+        return new UnwrappingBeanPropertyWriter(this, new SerializedString(newName));
     }
     
     @Override
@@ -78,7 +94,7 @@
             serializer = provider.findValueSerializer(type, this);
         }
         if (!serializer.isUnwrappingSerializer()) {
-            serializer = serializer.unwrappingSerializer();
+            serializer = serializer.unwrappingSerializer(_prefix);
         }
         _dynamicSerializers = _dynamicSerializers.newWith(type, serializer);
         return serializer;
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnwrappingBeanSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnwrappingBeanSerializer.java
index da4087b..7ab3c7d 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnwrappingBeanSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnwrappingBeanSerializer.java
@@ -7,7 +7,6 @@
 import com.fasterxml.jackson.databind.ser.*;
 import com.fasterxml.jackson.databind.ser.std.BeanSerializerBase;
 
-
 public class UnwrappingBeanSerializer
     extends BeanSerializerBase
 {
@@ -21,8 +20,8 @@
      * Constructor used for creating unwrapping instance of a
      * standard <code>BeanSerializer</code>
      */
-    public UnwrappingBeanSerializer(BeanSerializerBase src) {
-        super(src);
+    public UnwrappingBeanSerializer(BeanSerializerBase src, String prefix) {
+        super(src, prefix);
     }
 
     /*
@@ -32,8 +31,10 @@
      */
 
     @Override
-    public JsonSerializer<Object> unwrappingSerializer() {
-        // already unwrapping, nothing more to do:
+    public JsonSerializer<Object> unwrappingSerializer(String prefix) {
+        /* !!! 13-Jan-2011, tatu: do we need to do something here?
+         *    Would this affect multi-level unwrapping?
+         */
         return this;
     }
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/BeanSerializerBase.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/BeanSerializerBase.java
index b4cd876..19d258b 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/BeanSerializerBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/BeanSerializerBase.java
@@ -96,6 +96,34 @@
         this(src._handledType,
                 src._props, src._filteredProps, src._anyGetterWriter, src._propertyFilterId);
     }
+
+    /**
+     * Copy-constructor that will also rename properties with given prefix
+     * (if it's non-empty)
+     */
+    protected BeanSerializerBase(BeanSerializerBase src, String propertyPrefix) {
+        this(src._handledType,
+                appendPrefix(src._props, propertyPrefix),
+                appendPrefix(src._filteredProps, propertyPrefix),
+                src._anyGetterWriter, src._propertyFilterId);
+    }
+
+    private final static BeanPropertyWriter[] appendPrefix(BeanPropertyWriter[] props,
+            String prefix)
+    {
+        if (prefix == null || prefix.length() == 0 || props == null || props.length == 0) {
+            return props;
+        }
+        final int len = props.length;
+        BeanPropertyWriter[] result = new BeanPropertyWriter[len];
+        for (int i = 0; i < len; ++i) {
+            BeanPropertyWriter bpw = props[i];
+            if (bpw != null) {
+                result[i] = bpw.withName(prefix + bpw.getName());
+            }
+        }
+        return result;
+    }
     
     /*
     /**********************************************************
diff --git a/src/test/java/com/fasterxml/jackson/databind/struct/TestUnwrapping.java b/src/test/java/com/fasterxml/jackson/databind/struct/TestUnwrapping.java
index ff054cc..770bdb0 100644
--- a/src/test/java/com/fasterxml/jackson/databind/struct/TestUnwrapping.java
+++ b/src/test/java/com/fasterxml/jackson/databind/struct/TestUnwrapping.java
@@ -68,26 +68,67 @@
             unwrapped = new Unwrapping(str, x, y);
         }
     }
+
+    // Class with unwrapping using prefixes
+    static class PrefixUnwrap
+    {
+        public String name;
+        @JsonUnwrapped(prefix="_")
+        public Location location;
+
+        public PrefixUnwrap() { }
+        public PrefixUnwrap(String str, int x, int y) {
+            name = str;
+            location = new Location(x, y);
+        }
+    }
+
+    /*
+    static class DeepPrefixUnwrap
+    {
+        @JsonUnwrapped(prefix="u")
+        public PrefixUnwrap unwrapped;
+
+        public DeepPrefixUnwrap() { }
+        public DeepPrefixUnwrap(String str, int x, int y) {
+            unwrapped = new PrefixUnwrap(str, x, y);
+        }
+    }*/
     
     /*
     /**********************************************************
     /* Tests, serialization
     /**********************************************************
      */
+
+    private final ObjectMapper mapper = new ObjectMapper();
     
     public void testSimpleUnwrappingSerialize() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
         assertEquals("{\"name\":\"Tatu\",\"x\":1,\"y\":2}",
-                m.writeValueAsString(new Unwrapping("Tatu", 1, 2)));
+                mapper.writeValueAsString(new Unwrapping("Tatu", 1, 2)));
     }
 
+    public void testPrefixedUnwrappingSerialize() throws Exception
+    {
+        assertEquals("{\"name\":\"Tatu\",\"_x\":1,\"_y\":2}",
+                mapper.writeValueAsString(new PrefixUnwrap("Tatu", 1, 2)));
+    }
+    
     public void testDeepUnwrappingSerialize() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
         assertEquals("{\"name\":\"Tatu\",\"x\":1,\"y\":2}",
-                m.writeValueAsString(new DeepUnwrapping("Tatu", 1, 2)));
+                mapper.writeValueAsString(new DeepUnwrapping("Tatu", 1, 2)));
     }
+
+    // 13-Jan-2012, tatu: does not quite work yet -- should, need to investigate:
+    /*
+    public void testDeepPrefixedUnwrappingSerialize() throws Exception
+    {
+        assertEquals("{\"name\":\"Bubba\",\"u_x\":1,\"u_y\":1}",
+                mapper.writeValueAsString(new DeepPrefixUnwrap("Bubba", 1, 1)));
+    }
+    */
     
     /*
     /**********************************************************
@@ -97,8 +138,7 @@
     
     public void testSimpleUnwrappedDeserialize() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        Unwrapping bean = m.readValue("{\"name\":\"Tatu\",\"y\":7,\"x\":-13}",
+        Unwrapping bean = mapper.readValue("{\"name\":\"Tatu\",\"y\":7,\"x\":-13}",
                 Unwrapping.class);
         assertEquals("Tatu", bean.name);
         Location loc = bean.location;
@@ -106,11 +146,10 @@
         assertEquals(-13, loc.x);
         assertEquals(7, loc.y);
     }
-
+    
     public void testDoubleUnwrapping() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        TwoUnwrappedProperties bean = m.readValue("{\"first\":\"Joe\",\"y\":7,\"last\":\"Smith\",\"x\":-13}",
+        TwoUnwrappedProperties bean = mapper.readValue("{\"first\":\"Joe\",\"y\":7,\"last\":\"Smith\",\"x\":-13}",
                 TwoUnwrappedProperties.class);
         Location loc = bean.location;
         assertNotNull(loc);
@@ -121,11 +160,10 @@
         assertEquals("Joe", name.first);
         assertEquals("Smith", name.last);
     }
-
+    
     public void testDeepUnwrapping() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        DeepUnwrapping bean = m.readValue("{\"x\":3,\"name\":\"Bob\",\"y\":27}",
+        DeepUnwrapping bean = mapper.readValue("{\"x\":3,\"name\":\"Bob\",\"y\":27}",
                 DeepUnwrapping.class);
         Unwrapping uw = bean.unwrapped;
         assertNotNull(uw);
@@ -138,8 +176,7 @@
     
     public void testUnwrappedDeserializeWithCreator() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        UnwrappingWithCreator bean = m.readValue("{\"x\":1,\"y\":2,\"name\":\"Tatu\"}",
+        UnwrappingWithCreator bean = mapper.readValue("{\"x\":1,\"y\":2,\"name\":\"Tatu\"}",
                 UnwrappingWithCreator.class);
         assertEquals("Tatu", bean.name);
         Location loc = bean.location;
@@ -147,5 +184,14 @@
         assertEquals(1, loc.x);
         assertEquals(2, loc.y);
     }
-    
+
+    public void testPrefixedUnwrapping() throws Exception
+    {
+        PrefixUnwrap bean = mapper.readValue("{\"name\":\"Axel\",\"_x\":4,\"_y\":7}", PrefixUnwrap.class);
+        assertNotNull(bean);
+        assertEquals("Axel", bean.name);
+        assertNotNull(bean.location);
+        assertEquals(4, bean.location.x);
+        assertEquals(7, bean.location.y);
+    }
 }