Repository: mitchellh/mapstructure (go)

Issue:
Decoding to pointers with nil value
Mapstructure is very useful and great library, thank you!

But many gophers use pointer type for know whether value is absent, or whether not.
The problem that mapstructure could not properly decode map values into struct field that is pointer.

**Example:**
We have target struct

```go
type Result struct {
	T *time.Time
}
```

and have a decode hook, which try to parse *string* to **time.Time*

```go
func (f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
	if t == reflect.TypeOf(&time.Time{}) && f.Kind() == reflect.String && data == "" {
		return nil, nil
	}
        
        ...

	return data, nil
}
```

After decoding
***I would like to expect***
```
type Result struct {
	T *time.Time // nil
}
```
***But I got***
```
type Result struct {
	T *time.Time // 0001-01-01 00:00:00 +0000 UTC
}
```

The reason is that *decodePtr* function creates zero value for *valElemType*
```go
if realVal.IsNil() || d.config.ZeroFields {
	realVal = reflect.New(valElemType)
}
```

**Question**
Maybe we wont create zero value if data is nil and ZeroFields is false?
Or we can create specific tag for fields that could have nil value after decoding.

Pull request:
Check input for nil before and after decode hook.
If input data is nil before decoding, we bail out early, but if decoding
a non-nil value returns a nil value, we continue with the decode method
and return a zero value. As described in #97, this makes it impossible
to return a nil value from a decode hook. This patch checks for nil
inputs before and after decoding.

[Fixes #97]

Patch:
diff --git a/mapstructure.go b/mapstructure.go
index d3222b8..15d21ca 100644
--- a/mapstructure.go
+++ b/mapstructure.go
@@ -257,6 +257,18 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e
 		if err != nil {
 			return fmt.Errorf("error decoding '%s': %s", name, err)
 		}
+		if input == nil {
+			// If the data is nil, then we don't set anything, unless ZeroFields is set
+			// to true.
+			if d.config.ZeroFields {
+				outVal.Set(reflect.Zero(outVal.Type()))
+
+				if d.config.Metadata != nil && name != "" {
+					d.config.Metadata.Keys = append(d.config.Metadata.Keys, name)
+				}
+			}
+			return nil
+		}
 	}
 
 	var err error


Test patch:
diff --git a/mapstructure_test.go b/mapstructure_test.go
index 344ffa3..36b84ff 100644
--- a/mapstructure_test.go
+++ b/mapstructure_test.go
@@ -83,6 +83,10 @@ type NilInterface struct {
 	W io.Writer
 }
 
+type NilPointer struct {
+	Value *string
+}
+
 type Slice struct {
 	Vfoo string
 	Vbar []string
@@ -627,6 +631,43 @@ func TestDecode_NilInterfaceHook(t *testing.T) {
 	}
 }
 
+func TestDecode_NilPointerHook(t *testing.T) {
+	t.Parallel()
+
+	input := map[string]interface{}{
+		"value": "",
+	}
+
+	decodeHook := func(f, t reflect.Type, v interface{}) (interface{}, error) {
+		if typed, ok := v.(string); ok {
+			if typed == "" {
+				return nil, nil
+			}
+		}
+		return v, nil
+	}
+
+	var result NilPointer
+	config := &DecoderConfig{
+		DecodeHook: decodeHook,
+		Result:     &result,
+	}
+
+	decoder, err := NewDecoder(config)
+	if err != nil {
+		t.Fatalf("err: %s", err)
+	}
+
+	err = decoder.Decode(input)
+	if err != nil {
+		t.Fatalf("got an err: %s", err)
+	}
+
+	if result.Value != nil {
+		t.Errorf("W should be nil: %#v", result.Value)
+	}
+}
+
 func TestDecode_FuncHook(t *testing.T) {
 	t.Parallel()