1
0
mirror of https://github.com/json-iterator/go.git synced 2025-07-03 23:30:41 +02:00

feature #384: Specify custom map key sort function

This commit is contained in:
Zach McElrath
2019-07-09 15:57:36 -04:00
parent 27518f6661
commit 3e68b32b9a
5 changed files with 130 additions and 10 deletions

View File

@ -28,6 +28,7 @@ func encoderOfMap(ctx *ctx, typ reflect2.Type) ValEncoder {
return &sortKeysMapEncoder{
mapType: mapType,
keyEncoder: encoderOfMapKey(ctx.append("[mapKey]"), mapType.Key()),
keySorter: sorterOfMapKey(ctx),
elemEncoder: encoderOfType(ctx.append("[mapElem]"), mapType.Elem()),
}
}
@ -38,6 +39,23 @@ func encoderOfMap(ctx *ctx, typ reflect2.Type) ValEncoder {
}
}
type defaultMapKeySorter struct {
}
func (sorter defaultMapKeySorter) Sort(keyA string, keyB string) bool {
return keyA < keyB
}
func sorterOfMapKey(ctx *ctx) MapKeySorter {
for _, extension := range ctx.extraExtensions {
sorter := extension.CreateMapKeySorter()
if sorter != nil {
return sorter
}
}
return defaultMapKeySorter{}
}
func decoderOfMapKey(ctx *ctx, typ reflect2.Type) ValDecoder {
decoder := ctx.decoderExtension.CreateMapKeyDecoder(typ)
if decoder != nil {
@ -275,6 +293,7 @@ func (encoder *mapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
type sortKeysMapEncoder struct {
mapType *reflect2.UnsafeMapType
keyEncoder ValEncoder
keySorter MapKeySorter
elemEncoder ValEncoder
}
@ -287,7 +306,7 @@ func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
mapIter := encoder.mapType.UnsafeIterate(ptr)
subStream := stream.cfg.BorrowStream(nil)
subIter := stream.cfg.BorrowIterator(nil)
keyValues := encodedKeyValues{}
keyValues := []encodedKV{}
for mapIter.HasNext() {
subStream.buf = make([]byte, 0, 64)
key, elem := mapIter.UnsafeNext()
@ -309,7 +328,11 @@ func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
keyValue: subStream.Buffer(),
})
}
sort.Sort(keyValues)
keyValueWrapper := encodedKeyValues{
keySorter: encoder.keySorter,
values: keyValues,
}
sort.Sort(keyValueWrapper)
for i, keyValue := range keyValues {
if i != 0 {
stream.WriteMore()
@ -326,13 +349,18 @@ func (encoder *sortKeysMapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return !iter.HasNext()
}
type encodedKeyValues []encodedKV
type encodedKeyValues struct {
keySorter MapKeySorter
values []encodedKV
}
type encodedKV struct {
key string
keyValue []byte
}
func (sv encodedKeyValues) Len() int { return len(sv) }
func (sv encodedKeyValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
func (sv encodedKeyValues) Less(i, j int) bool { return sv[i].key < sv[j].key }
func (sv encodedKeyValues) Len() int { return len(sv.values) }
func (sv encodedKeyValues) Swap(i, j int) { sv.values[i], sv.values[j] = sv.values[j], sv.values[i] }
func (sv encodedKeyValues) Less(i, j int) bool {
return sv.keySorter.Sort(sv.values[i].key, sv.values[j].key)
}