You've already forked json-iterator
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:
@ -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)
|
||||
}
|
||||
|
Reference in New Issue
Block a user