@@ -3083,6 +3083,171 @@ func TestDecoder_IgnoreUntaggedFieldsWithStruct(t *testing.T) {
3083
3083
}
3084
3084
}
3085
3085
3086
+ func TestDecoder_CanPerformDecodingForNilInputs (t * testing.T ) {
3087
+ t .Parallel ()
3088
+
3089
+ type Transformed struct {
3090
+ Message string
3091
+ When string
3092
+ }
3093
+
3094
+ helloHook := func (reflect.Type , reflect.Type , interface {}) (interface {}, error ) {
3095
+ return Transformed {Message : "hello" }, nil
3096
+ }
3097
+ goodbyeHook := func (reflect.Type , reflect.Type , interface {}) (interface {}, error ) {
3098
+ return Transformed {Message : "goodbye" }, nil
3099
+ }
3100
+ appendHook := func (from reflect.Value , to reflect.Value ) (interface {}, error ) {
3101
+ if from .Kind () == reflect .Map {
3102
+ stringMap := from .Interface ().(map [string ]interface {})
3103
+ stringMap ["when" ] = "see you later"
3104
+ return stringMap , nil
3105
+ }
3106
+ return from .Interface (), nil
3107
+ }
3108
+
3109
+ tests := []struct {
3110
+ name string
3111
+ decodeNil bool
3112
+ input interface {}
3113
+ result Transformed
3114
+ expectedResult Transformed
3115
+ decodeHook DecodeHookFunc
3116
+ }{
3117
+ {
3118
+ name : "decodeNil=true for nil input with hook" ,
3119
+ decodeNil : true ,
3120
+ input : nil ,
3121
+ decodeHook : helloHook ,
3122
+ expectedResult : Transformed {Message : "hello" },
3123
+ },
3124
+ {
3125
+ name : "decodeNil=true for nil input without hook" ,
3126
+ decodeNil : true ,
3127
+ input : nil ,
3128
+ expectedResult : Transformed {Message : "" },
3129
+ },
3130
+ {
3131
+ name : "decodeNil=false for nil input with hook" ,
3132
+ decodeNil : false ,
3133
+ input : nil ,
3134
+ decodeHook : helloHook ,
3135
+ expectedResult : Transformed {Message : "" },
3136
+ },
3137
+ {
3138
+ name : "decodeNil=false for nil input without hook" ,
3139
+ decodeNil : false ,
3140
+ input : nil ,
3141
+ expectedResult : Transformed {Message : "" },
3142
+ },
3143
+ {
3144
+ name : "decodeNil=true for non-nil input without hook" ,
3145
+ decodeNil : true ,
3146
+ input : map [string ]interface {}{"message" : "bar" },
3147
+ expectedResult : Transformed {Message : "bar" },
3148
+ },
3149
+ {
3150
+ name : "decodeNil=true for non-nil input with hook" ,
3151
+ decodeNil : true ,
3152
+ input : map [string ]interface {}{"message" : "bar" },
3153
+ decodeHook : goodbyeHook ,
3154
+ expectedResult : Transformed {Message : "goodbye" },
3155
+ },
3156
+ {
3157
+ name : "decodeNil=false for non-nil input without hook" ,
3158
+ decodeNil : false ,
3159
+ input : map [string ]interface {}{"message" : "bar" },
3160
+ expectedResult : Transformed {Message : "bar" },
3161
+ },
3162
+ {
3163
+ name : "decodeNil=false for non-nil input with hook" ,
3164
+ decodeNil : false ,
3165
+ input : map [string ]interface {}{"message" : "bar" },
3166
+ decodeHook : goodbyeHook ,
3167
+ expectedResult : Transformed {Message : "goodbye" },
3168
+ },
3169
+ {
3170
+ name : "decodeNil=true for nil input without hook and non-empty result" ,
3171
+ decodeNil : true ,
3172
+ input : nil ,
3173
+ result : Transformed {Message : "foo" },
3174
+ expectedResult : Transformed {Message : "foo" },
3175
+ },
3176
+ {
3177
+ name : "decodeNil=true for nil input with hook and non-empty result" ,
3178
+ decodeNil : true ,
3179
+ input : nil ,
3180
+ result : Transformed {Message : "foo" },
3181
+ decodeHook : helloHook ,
3182
+ expectedResult : Transformed {Message : "hello" },
3183
+ },
3184
+ {
3185
+ name : "decodeNil=false for nil input without hook and non-empty result" ,
3186
+ decodeNil : false ,
3187
+ input : nil ,
3188
+ result : Transformed {Message : "foo" },
3189
+ expectedResult : Transformed {Message : "foo" },
3190
+ },
3191
+ {
3192
+ name : "decodeNil=false for nil input with hook and non-empty result" ,
3193
+ decodeNil : false ,
3194
+ input : nil ,
3195
+ result : Transformed {Message : "foo" },
3196
+ decodeHook : helloHook ,
3197
+ expectedResult : Transformed {Message : "foo" },
3198
+ },
3199
+ {
3200
+ name : "decodeNil=false for non-nil input with hook that appends a value" ,
3201
+ decodeNil : false ,
3202
+ input : map [string ]interface {}{"message" : "bar" },
3203
+ decodeHook : appendHook ,
3204
+ expectedResult : Transformed {Message : "bar" , When : "see you later" },
3205
+ },
3206
+ {
3207
+ name : "decodeNil=true for non-nil input with hook that appends a value" ,
3208
+ decodeNil : true ,
3209
+ input : map [string ]interface {}{"message" : "bar" },
3210
+ decodeHook : appendHook ,
3211
+ expectedResult : Transformed {Message : "bar" , When : "see you later" },
3212
+ },
3213
+ {
3214
+ name : "decodeNil=true for nil input with hook that appends a value" ,
3215
+ decodeNil : true ,
3216
+ decodeHook : appendHook ,
3217
+ expectedResult : Transformed {When : "see you later" },
3218
+ },
3219
+ {
3220
+ name : "decodeNil=false for nil input with hook that appends a value" ,
3221
+ decodeNil : false ,
3222
+ decodeHook : appendHook ,
3223
+ expectedResult : Transformed {},
3224
+ },
3225
+ }
3226
+
3227
+ for _ , test := range tests {
3228
+ t .Run (test .name , func (t * testing.T ) {
3229
+ config := & DecoderConfig {
3230
+ Result : & test .result ,
3231
+ DecodeNil : test .decodeNil ,
3232
+ DecodeHook : test .decodeHook ,
3233
+ }
3234
+
3235
+ decoder , err := NewDecoder (config )
3236
+ if err != nil {
3237
+ t .Fatalf ("err: %s" , err )
3238
+ }
3239
+
3240
+ if err := decoder .Decode (test .input ); err != nil {
3241
+ t .Fatalf ("got an err: %s" , err )
3242
+ }
3243
+
3244
+ if test .result != test .expectedResult {
3245
+ t .Errorf ("result should be: %#v, got %#v" , test .expectedResult , test .result )
3246
+ }
3247
+ })
3248
+ }
3249
+ }
3250
+
3086
3251
func testSliceInput (t * testing.T , input map [string ]interface {}, expected * Slice ) {
3087
3252
var result Slice
3088
3253
err := Decode (input , & result )
0 commit comments