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