diff --git a/pom.xml b/pom.xml
index b3f817c0..29fab04d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <groupId>com.jsoniter</groupId>
-    <version>0.9.23</version>
+    <version>0.9.24-SNAPSHOT</version>
     <artifactId>jsoniter</artifactId>
     <name>json iterator</name>
     <description>jsoniter (json-iterator) is fast and flexible JSON parser available in Java and Go</description>
@@ -155,6 +155,7 @@
                     </execution>
                 </executions>
             </plugin>
+
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-gpg-plugin</artifactId>
@@ -169,6 +170,7 @@
                     </execution>
                 </executions>
             </plugin>
+
             <plugin>
                 <groupId>org.sonatype.plugins</groupId>
                 <artifactId>nexus-staging-maven-plugin</artifactId>
diff --git a/src/main/java/com/jsoniter/output/CodegenImplObject.java b/src/main/java/com/jsoniter/output/CodegenImplObject.java
index 2e07f651..b2f03c88 100644
--- a/src/main/java/com/jsoniter/output/CodegenImplObject.java
+++ b/src/main/java/com/jsoniter/output/CodegenImplObject.java
@@ -12,41 +12,57 @@ public static CodegenResult genObject(ClassInfo classInfo) {
         List<EncodeTo> encodeTos = desc.encodeTos();
         ctx.append(String.format("public static void encode_(%s obj, com.jsoniter.output.JsonStream stream) throws java.io.IOException {", classInfo.clazz.getCanonicalName()));
         if (hasFieldOutput(desc)) {
-            int notFirst = 0;
-            if (noIndention) {
-                ctx.buffer('{');
-            } else {
-                ctx.append("stream.writeObjectStart();");
+            boolean isSimpleValue = false;
+            for(UnwrapperDescriptor unwarpper: desc.unwrappers) {
+                if (unwarpper.isSimpleValue) {
+                    isSimpleValue = true;
+                    break;
+                }
             }
-            for (EncodeTo encodeTo : encodeTos) {
-                notFirst = genField(ctx, encodeTo.binding, encodeTo.toName, notFirst);
+            if (isSimpleValue) {
+                UnwrapperDescriptor unwrapper = desc.unwrappers.get(0);
+                ctx.append(String.format("Object simpleValue = obj.%s();", unwrapper.method.getName()));
+                ctx.append("if (simpleValue == null) { stream.writeNull(); } else {");
+                CodegenImplNative.genWriteOp(ctx, "simpleValue", unwrapper.mapValueTypeLiteral.getType(), true);
+                ctx.append("}");
             }
-            for (UnwrapperDescriptor unwrapper : desc.unwrappers) {
-                if (unwrapper.isMap) {
-                    ctx.append(String.format("java.util.Map map = (java.util.Map)obj.%s();", unwrapper.method.getName()));
-                    ctx.append("java.util.Iterator iter = map.entrySet().iterator();");
-                    ctx.append("while(iter.hasNext()) {");
-                    ctx.append("java.util.Map.Entry entry = (java.util.Map.Entry)iter.next();");
-                    notFirst = appendComma(ctx, notFirst);
-                    ctx.append("stream.writeObjectField(entry.getKey().toString());");
-                    ctx.append("if (entry.getValue() == null) { stream.writeNull(); } else {");
-                    CodegenImplNative.genWriteOp(ctx, "entry.getValue()", unwrapper.mapValueTypeLiteral.getType(), true);
-                    ctx.append("}");
-                    ctx.append("}");
+            else {
+                int notFirst = 0;
+                if (noIndention) {
+                    ctx.buffer('{');
                 } else {
-                    notFirst = appendComma(ctx, notFirst);
-                    ctx.append(String.format("obj.%s(stream);", unwrapper.method.getName()));
+                    ctx.append("stream.writeObjectStart();");
                 }
-            }
-            if (noIndention) {
-                ctx.buffer('}');
-            } else {
-                if (notFirst == 1) { // definitely not first
-                    ctx.append("stream.writeObjectEnd();");
-                } else if (notFirst == 2) { // // maybe not first, previous field is omitNull
-                    ctx.append("if (notFirst) { stream.writeObjectEnd(); } else { stream.write('}'); }");
-                } else { // this is the first
-                    ctx.append("stream.write('}');");
+                for (EncodeTo encodeTo : encodeTos) {
+                    notFirst = genField(ctx, encodeTo.binding, encodeTo.toName, notFirst);
+                }
+                for (UnwrapperDescriptor unwrapper : desc.unwrappers) {
+                    if (unwrapper.isMap) {
+                        ctx.append(String.format("java.util.Map map = (java.util.Map)obj.%s();", unwrapper.method.getName()));
+                        ctx.append("java.util.Iterator iter = map.entrySet().iterator();");
+                        ctx.append("while(iter.hasNext()) {");
+                        ctx.append("java.util.Map.Entry entry = (java.util.Map.Entry)iter.next();");
+                        notFirst = appendComma(ctx, notFirst);
+                        ctx.append("stream.writeObjectField(entry.getKey().toString());");
+                        ctx.append("if (entry.getValue() == null) { stream.writeNull(); } else {");
+                        CodegenImplNative.genWriteOp(ctx, "entry.getValue()", unwrapper.mapValueTypeLiteral.getType(), true);
+                        ctx.append("}");
+                        ctx.append("}");
+                    } else {
+                        notFirst = appendComma(ctx, notFirst);
+                        ctx.append(String.format("obj.%s(stream);", unwrapper.method.getName()));
+                    }
+                }
+                if (noIndention) {
+                    ctx.buffer('}');
+                } else {
+                    if (notFirst == 1) { // definitely not first
+                        ctx.append("stream.writeObjectEnd();");
+                    } else if (notFirst == 2) { // // maybe not first, previous field is omitNull
+                        ctx.append("if (notFirst) { stream.writeObjectEnd(); } else { stream.write('}'); }");
+                    } else { // this is the first
+                        ctx.append("stream.write('}');");
+                    }
                 }
             }
         } else {
diff --git a/src/main/java/com/jsoniter/output/ReflectionObjectEncoder.java b/src/main/java/com/jsoniter/output/ReflectionObjectEncoder.java
index 99c256c3..ec5fea82 100644
--- a/src/main/java/com/jsoniter/output/ReflectionObjectEncoder.java
+++ b/src/main/java/com/jsoniter/output/ReflectionObjectEncoder.java
@@ -67,42 +67,56 @@ private void enocde_(Object obj, JsonStream stream) throws Exception {
             stream.writeNull();
             return;
         }
-        stream.writeObjectStart();
-        boolean notFirst = false;
-        for (EncodeTo encodeTo : fields) {
-            Object val = encodeTo.binding.field.get(obj);
-            notFirst = writeEncodeTo(stream, notFirst, encodeTo, val);
+        boolean isSimpleValue = false;
+        for(UnwrapperDescriptor unwarpper: desc.unwrappers) {
+            if (unwarpper.isSimpleValue) {
+                isSimpleValue = true;
+                break;
+            }
         }
-        for (EncodeTo encodeTo : getters) {
-            Object val = encodeTo.binding.method.invoke(obj);
-            notFirst = writeEncodeTo(stream, notFirst, encodeTo, val);
+        if (isSimpleValue) {
+            UnwrapperDescriptor unwrapper = desc.unwrappers.get(0);
+            Object simpleValue = unwrapper.method.invoke(obj);
+            stream.writeVal(unwrapper.mapValueTypeLiteral, simpleValue);
         }
-        for (UnwrapperDescriptor unwrapper : desc.unwrappers) {
-            if (unwrapper.isMap) {
-                Map<Object, Object> map = (Map<Object, Object>) unwrapper.method.invoke(obj);
-                for (Map.Entry<Object, Object> entry : map.entrySet()) {
+        else {
+            stream.writeObjectStart();
+            boolean notFirst = false;
+            for (EncodeTo encodeTo : fields) {
+                Object val = encodeTo.binding.field.get(obj);
+                notFirst = writeEncodeTo(stream, notFirst, encodeTo, val);
+            }
+            for (EncodeTo encodeTo : getters) {
+                Object val = encodeTo.binding.method.invoke(obj);
+                notFirst = writeEncodeTo(stream, notFirst, encodeTo, val);
+            }
+            for (UnwrapperDescriptor unwrapper : desc.unwrappers) {
+                if (unwrapper.isMap) {
+                    Map<Object, Object> map = (Map<Object, Object>) unwrapper.method.invoke(obj);
+                    for (Map.Entry<Object, Object> entry : map.entrySet()) {
+                        if (notFirst) {
+                            stream.writeMore();
+                        } else {
+                            notFirst = true;
+                        }
+                        stream.writeObjectField(entry.getKey().toString());
+                        stream.writeVal(unwrapper.mapValueTypeLiteral, entry.getValue());
+                    }
+                } else {
                     if (notFirst) {
                         stream.writeMore();
                     } else {
                         notFirst = true;
                     }
-                    stream.writeObjectField(entry.getKey().toString());
-                    stream.writeVal(unwrapper.mapValueTypeLiteral, entry.getValue());
+                    unwrapper.method.invoke(obj, stream);
                 }
+            }
+            if (notFirst) {
+                stream.writeObjectEnd();
             } else {
-                if (notFirst) {
-                    stream.writeMore();
-                } else {
-                    notFirst = true;
-                }
-                unwrapper.method.invoke(obj, stream);
+                stream.write('}');
             }
         }
-        if (notFirst) {
-            stream.writeObjectEnd();
-        } else {
-            stream.write('}');
-        }
     }
 
     private boolean writeEncodeTo(JsonStream stream, boolean notFirst, EncodeTo encodeTo, Object val) throws IOException {
diff --git a/src/main/java/com/jsoniter/spi/Config.java b/src/main/java/com/jsoniter/spi/Config.java
index 5b0d6c98..e689d469 100644
--- a/src/main/java/com/jsoniter/spi/Config.java
+++ b/src/main/java/com/jsoniter/spi/Config.java
@@ -255,6 +255,7 @@ public void updateClassDescriptor(ClassDescriptor desc) {
     }
 
     private void detectUnwrappers(ClassDescriptor desc, List<Method> allMethods) {
+        boolean isSimpleValue = false;
         for (Method method : allMethods) {
             if (Modifier.isStatic(method.getModifiers())) {
                 continue;
@@ -262,7 +263,16 @@ private void detectUnwrappers(ClassDescriptor desc, List<Method> allMethods) {
             if (getJsonUnwrapper(method.getAnnotations()) == null) {
                 continue;
             }
-            desc.unwrappers.add(new UnwrapperDescriptor(method));
+            UnwrapperDescriptor unwarpper = new UnwrapperDescriptor(method);
+            if (unwarpper.isSimpleValue) {
+                if (isSimpleValue) {
+                    throw new JsonException("Multiple @JsonUnwrapper on simple value getter");
+                }
+                else {
+                    isSimpleValue = true;
+                }
+            }
+            desc.unwrappers.add(unwarpper);
         }
     }
 
diff --git a/src/main/java/com/jsoniter/spi/UnwrapperDescriptor.java b/src/main/java/com/jsoniter/spi/UnwrapperDescriptor.java
index eb758054..d18a5976 100644
--- a/src/main/java/com/jsoniter/spi/UnwrapperDescriptor.java
+++ b/src/main/java/com/jsoniter/spi/UnwrapperDescriptor.java
@@ -13,6 +13,8 @@ public class UnwrapperDescriptor {
 
     public boolean isMap;
 
+    public boolean isSimpleValue;
+
     public TypeLiteral mapValueTypeLiteral;
 
     public UnwrapperDescriptor(Method method) {
@@ -30,7 +32,12 @@ public UnwrapperDescriptor(Method method) {
             }
         } else if (isStreamUnwrapper(method)) {
             this.isMap = false;
-        } else {
+        } else if (method.getParameterTypes().length == 0 && method.getReturnType() != void.class) { //A getter
+            this.isSimpleValue = true;
+            Type mapType = method.getReturnType();
+            mapValueTypeLiteral = TypeLiteral.create(mapType);
+        }
+        else {
             throw new JsonException("invalid unwrapper method signature: " + method);
         }
     }
diff --git a/src/test/java/com/jsoniter/output/TestAnnotationJsonUnwrapper.java b/src/test/java/com/jsoniter/output/TestAnnotationJsonUnwrapper.java
index 9ad9f66c..7ba8f228 100644
--- a/src/test/java/com/jsoniter/output/TestAnnotationJsonUnwrapper.java
+++ b/src/test/java/com/jsoniter/output/TestAnnotationJsonUnwrapper.java
@@ -48,4 +48,34 @@ public void test_unwrapper_with_map() throws IOException {
         stream.close();
         assertEquals("{\"100\":\"hello\"}", baos.toString());
     }
+
+
+    /**
+     * Consider the getter result as the entire json object
+     * Similar as @JsonValue in jackson
+     */
+    public static class TestObject3 {
+
+        private String name;
+
+        public String getName() {
+            return name;
+        }
+
+        public void setName(String name) {
+            this.name = name;
+        }
+
+        @JsonUnwrapper
+        public String getValue() {
+            return "hello";
+        }
+    }
+
+    public void test_unwrapper_with_simple_value() throws IOException {
+        TestObject3 obj = new TestObject3();
+        stream.writeVal(obj);
+        stream.close();
+        assertEquals("\"hello\"", baos.toString());
+    }
 }