decoder_util.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. package json
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "io"
  7. )
  8. // DiscardUnknownField discards unknown fields from a decoder body.
  9. // This function is useful while deserializing a JSON body with additional
  10. // unknown information that should be discarded.
  11. func DiscardUnknownField(decoder *json.Decoder) error {
  12. // This deliberately does not share logic with CollectUnknownField, even
  13. // though it could, because if we were to delegate to that then we'd incur
  14. // extra allocations and general memory usage.
  15. v, err := decoder.Token()
  16. if err == io.EOF {
  17. return nil
  18. }
  19. if err != nil {
  20. return err
  21. }
  22. if _, ok := v.(json.Delim); ok {
  23. for decoder.More() {
  24. err = DiscardUnknownField(decoder)
  25. }
  26. endToken, err := decoder.Token()
  27. if err != nil {
  28. return err
  29. }
  30. if _, ok := endToken.(json.Delim); !ok {
  31. return fmt.Errorf("invalid JSON : expected json delimiter, found %T %v",
  32. endToken, endToken)
  33. }
  34. }
  35. return nil
  36. }
  37. // CollectUnknownField grabs the contents of unknown fields from the decoder body
  38. // and returns them as a byte slice. This is useful for skipping unknown fields without
  39. // completely discarding them.
  40. func CollectUnknownField(decoder *json.Decoder) ([]byte, error) {
  41. result, err := collectUnknownField(decoder)
  42. if err != nil {
  43. return nil, err
  44. }
  45. buff := bytes.NewBuffer(nil)
  46. encoder := json.NewEncoder(buff)
  47. if err := encoder.Encode(result); err != nil {
  48. return nil, err
  49. }
  50. return buff.Bytes(), nil
  51. }
  52. func collectUnknownField(decoder *json.Decoder) (interface{}, error) {
  53. // Grab the initial value. This could either be a concrete value like a string or a a
  54. // delimiter.
  55. token, err := decoder.Token()
  56. if err == io.EOF {
  57. return nil, nil
  58. }
  59. if err != nil {
  60. return nil, err
  61. }
  62. // If it's an array or object, we'll need to recurse.
  63. delim, ok := token.(json.Delim)
  64. if ok {
  65. var result interface{}
  66. if delim == '{' {
  67. result, err = collectUnknownObject(decoder)
  68. if err != nil {
  69. return nil, err
  70. }
  71. } else {
  72. result, err = collectUnknownArray(decoder)
  73. if err != nil {
  74. return nil, err
  75. }
  76. }
  77. // Discard the closing token. decoder.Token handles checking for matching delimiters
  78. if _, err := decoder.Token(); err != nil {
  79. return nil, err
  80. }
  81. return result, nil
  82. }
  83. return token, nil
  84. }
  85. func collectUnknownArray(decoder *json.Decoder) ([]interface{}, error) {
  86. // We need to create an empty array here instead of a nil array, since by getting
  87. // into this function at all we necessarily have seen a non-nil list.
  88. array := []interface{}{}
  89. for decoder.More() {
  90. value, err := collectUnknownField(decoder)
  91. if err != nil {
  92. return nil, err
  93. }
  94. array = append(array, value)
  95. }
  96. return array, nil
  97. }
  98. func collectUnknownObject(decoder *json.Decoder) (map[string]interface{}, error) {
  99. object := make(map[string]interface{})
  100. for decoder.More() {
  101. key, err := collectUnknownField(decoder)
  102. if err != nil {
  103. return nil, err
  104. }
  105. // Keys have to be strings, which is particularly important as the encoder
  106. // won't except a map with interface{} keys
  107. stringKey, ok := key.(string)
  108. if !ok {
  109. return nil, fmt.Errorf("expected string key, found %T", key)
  110. }
  111. value, err := collectUnknownField(decoder)
  112. if err != nil {
  113. return nil, err
  114. }
  115. object[stringKey] = value
  116. }
  117. return object, nil
  118. }