Skip to content

Commit c186b73

Browse files
committed
fix quoting value even when not applicable
1 parent b661cd9 commit c186b73

File tree

3 files changed

+81
-11
lines changed

3 files changed

+81
-11
lines changed

reflect_extension.go

+17-6
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ package jsoniter
22

33
import (
44
"fmt"
5-
"github.com/modern-go/reflect2"
65
"reflect"
76
"sort"
87
"strings"
98
"unicode"
109
"unsafe"
10+
11+
"github.com/modern-go/reflect2"
1112
)
1213

1314
var typeDecoders = map[string]ValDecoder{}
@@ -448,12 +449,22 @@ func processTags(structDescriptor *StructDescriptor, cfg *frozenConfig) {
448449
if tagPart == "omitempty" {
449450
shouldOmitEmpty = true
450451
} else if tagPart == "string" {
451-
if binding.Field.Type().Kind() == reflect.String {
452-
binding.Decoder = &stringModeStringDecoder{binding.Decoder, cfg}
453-
binding.Encoder = &stringModeStringEncoder{binding.Encoder, cfg}
454-
} else {
452+
fieldType := binding.Field.Type()
453+
isPointer := false
454+
if fieldType.Kind() == reflect.Pointer {
455+
isPointer = true
456+
fieldType = reflect2.Type2(fieldType.Type1().Elem())
457+
}
458+
switch fieldType.Kind() {
459+
case reflect.String:
460+
binding.Decoder = &stringModeStringDecoder{isPointer, binding.Decoder, cfg}
461+
binding.Encoder = &stringModeStringEncoder{isPointer, binding.Encoder, cfg}
462+
case reflect.Float32, reflect.Float64,
463+
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
464+
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
465+
reflect.Bool:
455466
binding.Decoder = &stringModeNumberDecoder{binding.Decoder}
456-
binding.Encoder = &stringModeNumberEncoder{binding.Encoder}
467+
binding.Encoder = &stringModeNumberEncoder{isPointer, binding.Encoder}
457468
}
458469
}
459470
}

reflect_struct_decoder.go

+45-2
Original file line numberDiff line numberDiff line change
@@ -1058,16 +1058,59 @@ func (decoder *structFieldDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
10581058
}
10591059

10601060
type stringModeStringDecoder struct {
1061+
isPointer bool // true indicates *string field type.
10611062
elemDecoder ValDecoder
10621063
cfg *frozenConfig
10631064
}
10641065

10651066
func (decoder *stringModeStringDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
10661067
decoder.elemDecoder.Decode(ptr, iter)
1067-
str := *((*string)(ptr))
1068+
1069+
if iter.Error != nil {
1070+
return
1071+
}
1072+
1073+
var str string
1074+
if decoder.isPointer {
1075+
if *((**string)(ptr)) == nil {
1076+
return
1077+
}
1078+
str = **((**string)(ptr))
1079+
} else {
1080+
str = *((*string)(ptr))
1081+
}
1082+
1083+
if len(str) < 2 {
1084+
iter.ReportError(
1085+
"stringModeStringDecoder",
1086+
`expect len(s) >= 2, but found `+str,
1087+
)
1088+
return
1089+
}
1090+
if str[0] != '"' || str[len(str)-1] != '"' {
1091+
var idx int
1092+
if str[0] == '"' {
1093+
idx = len(str) - 1
1094+
}
1095+
iter.ReportError(
1096+
"stringModeStringDecoder",
1097+
`expect ", but found `+string(str[idx]),
1098+
)
1099+
return
1100+
}
1101+
10681102
tempIter := decoder.cfg.BorrowIterator([]byte(str))
10691103
defer decoder.cfg.ReturnIterator(tempIter)
1070-
*((*string)(ptr)) = tempIter.ReadString()
1104+
1105+
if decoder.isPointer {
1106+
**((**string)(ptr)) = tempIter.ReadString()
1107+
} else {
1108+
*((*string)(ptr)) = tempIter.ReadString()
1109+
}
1110+
1111+
if tempIter.Error != nil {
1112+
iter.Error = tempIter.Error
1113+
}
10711114
}
10721115

10731116
type stringModeNumberDecoder struct {

reflect_struct_encoder.go

+19-3
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ package jsoniter
22

33
import (
44
"fmt"
5-
"github.com/modern-go/reflect2"
65
"io"
76
"reflect"
87
"unsafe"
8+
9+
"github.com/modern-go/reflect2"
910
)
1011

1112
func encoderOfStruct(ctx *ctx, typ reflect2.Type) ValEncoder {
@@ -180,25 +181,40 @@ func (encoder *emptyStructEncoder) IsEmpty(ptr unsafe.Pointer) bool {
180181
}
181182

182183
type stringModeNumberEncoder struct {
184+
isPointer bool
183185
elemEncoder ValEncoder
184186
}
185187

186188
func (encoder *stringModeNumberEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
187-
stream.writeByte('"')
189+
shouldQuote := true
190+
if encoder.isPointer && ((*reflect2.UnsafePtrType)(nil)).UnsafeIsNil(ptr) {
191+
shouldQuote = false
192+
}
193+
if shouldQuote {
194+
stream.writeByte('"')
195+
}
188196
encoder.elemEncoder.Encode(ptr, stream)
189-
stream.writeByte('"')
197+
if shouldQuote {
198+
stream.writeByte('"')
199+
}
190200
}
191201

192202
func (encoder *stringModeNumberEncoder) IsEmpty(ptr unsafe.Pointer) bool {
193203
return encoder.elemEncoder.IsEmpty(ptr)
194204
}
195205

196206
type stringModeStringEncoder struct {
207+
isPointer bool
197208
elemEncoder ValEncoder
198209
cfg *frozenConfig
199210
}
200211

201212
func (encoder *stringModeStringEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
213+
if encoder.isPointer && ((*reflect2.UnsafePtrType)(nil)).UnsafeIsNil(ptr) {
214+
encoder.elemEncoder.Encode(ptr, stream)
215+
return
216+
}
217+
202218
tempStream := encoder.cfg.BorrowStream(nil)
203219
tempStream.Attachment = stream.Attachment
204220
defer encoder.cfg.ReturnStream(tempStream)

0 commit comments

Comments
 (0)