json.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. package orderedmap
  2. import (
  3. "bytes"
  4. "encoding"
  5. "encoding/json"
  6. "fmt"
  7. "reflect"
  8. "unicode/utf8"
  9. "github.com/buger/jsonparser"
  10. "github.com/mailru/easyjson/jwriter"
  11. )
  12. var (
  13. _ json.Marshaler = &OrderedMap[int, any]{}
  14. _ json.Unmarshaler = &OrderedMap[int, any]{}
  15. )
  16. // MarshalJSON implements the json.Marshaler interface.
  17. func (om *OrderedMap[K, V]) MarshalJSON() ([]byte, error) { //nolint:funlen
  18. if om == nil || om.list == nil {
  19. return []byte("null"), nil
  20. }
  21. writer := jwriter.Writer{}
  22. writer.RawByte('{')
  23. for pair, firstIteration := om.Oldest(), true; pair != nil; pair = pair.Next() {
  24. if firstIteration {
  25. firstIteration = false
  26. } else {
  27. writer.RawByte(',')
  28. }
  29. switch key := any(pair.Key).(type) {
  30. case string:
  31. writer.String(key)
  32. case encoding.TextMarshaler:
  33. writer.RawByte('"')
  34. writer.Raw(key.MarshalText())
  35. writer.RawByte('"')
  36. case int:
  37. writer.IntStr(key)
  38. case int8:
  39. writer.Int8Str(key)
  40. case int16:
  41. writer.Int16Str(key)
  42. case int32:
  43. writer.Int32Str(key)
  44. case int64:
  45. writer.Int64Str(key)
  46. case uint:
  47. writer.UintStr(key)
  48. case uint8:
  49. writer.Uint8Str(key)
  50. case uint16:
  51. writer.Uint16Str(key)
  52. case uint32:
  53. writer.Uint32Str(key)
  54. case uint64:
  55. writer.Uint64Str(key)
  56. default:
  57. // this switch takes care of wrapper types around primitive types, such as
  58. // type myType string
  59. switch keyValue := reflect.ValueOf(key); keyValue.Type().Kind() {
  60. case reflect.String:
  61. writer.String(keyValue.String())
  62. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  63. writer.Int64Str(keyValue.Int())
  64. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  65. writer.Uint64Str(keyValue.Uint())
  66. default:
  67. return nil, fmt.Errorf("unsupported key type: %T", key)
  68. }
  69. }
  70. writer.RawByte(':')
  71. // the error is checked at the end of the function
  72. writer.Raw(json.Marshal(pair.Value)) //nolint:errchkjson
  73. }
  74. writer.RawByte('}')
  75. return dumpWriter(&writer)
  76. }
  77. func dumpWriter(writer *jwriter.Writer) ([]byte, error) {
  78. if writer.Error != nil {
  79. return nil, writer.Error
  80. }
  81. var buf bytes.Buffer
  82. buf.Grow(writer.Size())
  83. if _, err := writer.DumpTo(&buf); err != nil {
  84. return nil, err
  85. }
  86. return buf.Bytes(), nil
  87. }
  88. // UnmarshalJSON implements the json.Unmarshaler interface.
  89. func (om *OrderedMap[K, V]) UnmarshalJSON(data []byte) error {
  90. if om.list == nil {
  91. om.initialize(0)
  92. }
  93. return jsonparser.ObjectEach(
  94. data,
  95. func(keyData []byte, valueData []byte, dataType jsonparser.ValueType, offset int) error {
  96. if dataType == jsonparser.String {
  97. // jsonparser removes the enclosing quotes; we need to restore them to make a valid JSON
  98. valueData = data[offset-len(valueData)-2 : offset]
  99. }
  100. var key K
  101. var value V
  102. switch typedKey := any(&key).(type) {
  103. case *string:
  104. s, err := decodeUTF8(keyData)
  105. if err != nil {
  106. return err
  107. }
  108. *typedKey = s
  109. case encoding.TextUnmarshaler:
  110. if err := typedKey.UnmarshalText(keyData); err != nil {
  111. return err
  112. }
  113. case *int, *int8, *int16, *int32, *int64, *uint, *uint8, *uint16, *uint32, *uint64:
  114. if err := json.Unmarshal(keyData, typedKey); err != nil {
  115. return err
  116. }
  117. default:
  118. // this switch takes care of wrapper types around primitive types, such as
  119. // type myType string
  120. switch reflect.TypeOf(key).Kind() {
  121. case reflect.String:
  122. s, err := decodeUTF8(keyData)
  123. if err != nil {
  124. return err
  125. }
  126. convertedKeyData := reflect.ValueOf(s).Convert(reflect.TypeOf(key))
  127. reflect.ValueOf(&key).Elem().Set(convertedKeyData)
  128. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
  129. reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  130. if err := json.Unmarshal(keyData, &key); err != nil {
  131. return err
  132. }
  133. default:
  134. return fmt.Errorf("unsupported key type: %T", key)
  135. }
  136. }
  137. if err := json.Unmarshal(valueData, &value); err != nil {
  138. return err
  139. }
  140. om.Set(key, value)
  141. return nil
  142. })
  143. }
  144. func decodeUTF8(input []byte) (string, error) {
  145. remaining, offset := input, 0
  146. runes := make([]rune, 0, len(remaining))
  147. for len(remaining) > 0 {
  148. r, size := utf8.DecodeRune(remaining)
  149. if r == utf8.RuneError && size <= 1 {
  150. return "", fmt.Errorf("not a valid UTF-8 string (at position %d): %s", offset, string(input))
  151. }
  152. runes = append(runes, r)
  153. remaining = remaining[size:]
  154. offset += size
  155. }
  156. return string(runes), nil
  157. }