1
0
mirror of https://github.com/json-iterator/go.git synced 2025-04-23 11:37:32 +02:00

#71 sort non string map keys

This commit is contained in:
Tao Wen 2017-06-26 10:42:47 +08:00
parent f771d32291
commit 0c07128d3c

View File

@ -156,17 +156,25 @@ func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
realVal := reflect.ValueOf(*realInterface) realVal := reflect.ValueOf(*realInterface)
// Extract and sort the keys. // Extract and sort the keys.
var sv stringValues = realVal.MapKeys() keys := realVal.MapKeys()
sort.Sort(sv) sv := make([]reflectWithString, len(keys))
for i, v := range keys {
sv[i].v = v
if err := sv[i].resolve(); err != nil {
stream.Error = err
return
}
}
sort.Slice(sv, func(i, j int) bool { return sv[i].s < sv[j].s })
stream.WriteObjectStart() stream.WriteObjectStart()
for i, key := range sv { for i, key := range sv {
if i != 0 { if i != 0 {
stream.WriteMore() stream.WriteMore()
} }
encodeMapKey(key, stream) stream.WriteString(key.s)
stream.writeByte(':') stream.writeByte(':')
val := realVal.MapIndex(key).Interface() val := realVal.MapIndex(key.v).Interface()
encoder.elemEncoder.EncodeInterface(val, stream) encoder.elemEncoder.EncodeInterface(val, stream)
} }
stream.WriteObjectEnd() stream.WriteObjectEnd()
@ -174,12 +182,37 @@ func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
// stringValues is a slice of reflect.Value holding *reflect.StringValue. // stringValues is a slice of reflect.Value holding *reflect.StringValue.
// It implements the methods to sort by string. // It implements the methods to sort by string.
type stringValues []reflect.Value type stringValues []reflectWithString
type reflectWithString struct {
v reflect.Value
s string
}
func (w *reflectWithString) resolve() error {
if w.v.Kind() == reflect.String {
w.s = w.v.String()
return nil
}
if tm, ok := w.v.Interface().(encoding.TextMarshaler); ok {
buf, err := tm.MarshalText()
w.s = string(buf)
return err
}
switch w.v.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
w.s = strconv.FormatInt(w.v.Int(), 10)
return nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
w.s = strconv.FormatUint(w.v.Uint(), 10)
return nil
}
return &json.UnsupportedTypeError{w.v.Type()}
}
func (sv stringValues) Len() int { return len(sv) } func (sv stringValues) Len() int { return len(sv) }
func (sv stringValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] } func (sv stringValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) } func (sv stringValues) Less(i, j int) bool { return sv[i].s < sv[j].s }
func (sv stringValues) get(i int) string { return sv[i].String() }
func (encoder *sortKeysMapEncoder) EncodeInterface(val interface{}, stream *Stream) { func (encoder *sortKeysMapEncoder) EncodeInterface(val interface{}, stream *Stream) {
WriteToStream(val, stream, encoder) WriteToStream(val, stream, encoder)