diff --git a/feature_reflect_native.go b/feature_reflect_native.go
index 4578c1a..aafe199 100644
--- a/feature_reflect_native.go
+++ b/feature_reflect_native.go
@@ -427,14 +427,14 @@ func (encoder *base64Codec) isEmpty(ptr unsafe.Pointer) bool {
 	return len(*((*[]byte)(ptr))) == 0
 }
 
-type stringNumberDecoder struct {
+type stringModeDecoder struct {
 	elemDecoder Decoder
 }
 
-func (decoder *stringNumberDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
+func (decoder *stringModeDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
 	c := iter.nextToken()
 	if c != '"' {
-		iter.reportError("stringNumberDecoder", `expect "`)
+		iter.reportError("stringModeDecoder", `expect "`)
 		return
 	}
 	decoder.elemDecoder.decode(ptr, iter)
@@ -443,11 +443,29 @@ func (decoder *stringNumberDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
 	}
 	c = iter.readByte()
 	if c != '"' {
-		iter.reportError("stringNumberDecoder", `expect "`)
+		iter.reportError("stringModeDecoder", `expect "`)
 		return
 	}
 }
 
+type stringModeEncoder struct {
+	elemEncoder Encoder
+}
+
+func (encoder *stringModeEncoder) encode(ptr unsafe.Pointer, stream *Stream) {
+	stream.writeByte('"')
+	encoder.elemEncoder.encode(ptr, stream)
+	stream.writeByte('"')
+}
+
+func (encoder *stringModeEncoder) encodeInterface(val interface{}, stream *Stream) {
+	writeToStream(val, stream, encoder)
+}
+
+func (encoder *stringModeEncoder) isEmpty(ptr unsafe.Pointer) bool {
+	return encoder.elemEncoder.isEmpty(ptr)
+}
+
 type marshalerEncoder struct {
 	templateInterface emptyInterface
 }
diff --git a/feature_reflect_object.go b/feature_reflect_object.go
index 9ea375f..8a2c94e 100644
--- a/feature_reflect_object.go
+++ b/feature_reflect_object.go
@@ -37,9 +37,12 @@ func encoderOfStruct(cfg *frozenConfig, typ reflect.Type) (Encoder, error) {
 		// if fieldNames set by extension, use theirs, otherwise try tags
 		fieldNames := calcFieldNames(field.Name, tagParts[0], extensionProvidedFieldNames)
 		omitempty := false
-		for _, tagPart := range tagParts {
+		stringMode := false
+		for _, tagPart := range tagParts[1:] {
 			if tagPart == "omitempty" {
 				omitempty = true
+			} else if tagPart == "string" {
+				stringMode = true
 			}
 		}
 		encoder := fieldEncoders[fieldEncoderKey]
@@ -54,6 +57,9 @@ func encoderOfStruct(cfg *frozenConfig, typ reflect.Type) (Encoder, error) {
 				encoder = &optionalEncoder{encoder}
 			}
 		}
+		if stringMode {
+			encoder = &stringModeEncoder{encoder}
+		}
 		for _, fieldName := range fieldNames {
 			fields[fieldName] = &structFieldEncoder{field, fieldName, encoder, omitempty}
 		}
@@ -114,8 +120,10 @@ func decoderOfStruct(cfg *frozenConfig, typ reflect.Type) (Decoder, error) {
 				return prefix(fmt.Sprintf("{%s}", field.Name)).addToDecoder(decoder, err)
 			}
 		}
-		if len(tagParts) > 1 && tagParts[1] == "string" {
-			decoder = &stringNumberDecoder{decoder}
+		for _, tagPart := range tagParts[1:] {
+			if tagPart == "string" {
+				decoder = &stringModeDecoder{decoder}
+			}
 		}
 		for _, fieldName := range fieldNames {
 			fields[fieldName] = &structFieldDecoder{&field, decoder}
diff --git a/jsoniter_bool_test.go b/jsoniter_bool_test.go
index bce0c3e..7785bd8 100644
--- a/jsoniter_bool_test.go
+++ b/jsoniter_bool_test.go
@@ -4,6 +4,7 @@ import (
 	"bytes"
 	"github.com/json-iterator/go/require"
 	"testing"
+	"encoding/json"
 )
 
 func Test_true(t *testing.T) {
@@ -47,3 +48,40 @@ func Test_write_val_bool(t *testing.T) {
 	should.Nil(stream.Error)
 	should.Equal("true", buf.String())
 }
+
+func Test_encode_string_bool(t *testing.T) {
+	type TestObject struct {
+		Field bool `json:",omitempty,string"`
+	}
+	should := require.New(t)
+	output, err := json.Marshal(TestObject{true})
+	should.Nil(err)
+	should.Equal(`{"Field":"true"}`, string(output))
+	output, err = Marshal(TestObject{true})
+	should.Nil(err)
+	should.Equal(`{"Field":"true"}`, string(output))
+}
+
+func Test_decode_string_bool(t *testing.T) {
+	type TestObject struct {
+		Field bool `json:",omitempty,string"`
+	}
+	should := require.New(t)
+	obj := TestObject{}
+	err := json.Unmarshal([]byte(`{"Field":"true"}`), &obj)
+	should.Nil(err)
+	should.True(obj.Field)
+
+	obj = TestObject{}
+	err = json.Unmarshal([]byte(`{"Field":true}`), &obj)
+	should.NotNil(err)
+
+	obj = TestObject{}
+	err = Unmarshal([]byte(`{"Field":"true"}`), &obj)
+	should.Nil(err)
+	should.True(obj.Field)
+
+	obj = TestObject{}
+	err = Unmarshal([]byte(`{"Field":true}`), &obj)
+	should.NotNil(err)
+}