func (sm *StructMapper) HasInverseAdapter(ty reflect.Type) bool {
	if sm.iadapters == nil {
		sm.iadapters = make(map[reflect.Type]InverseMapAdapter)
		return false
	}
	if ty.Kind() == reflect.Ptr {
		ty = ty.Elem()
	}
	_, exists := sm.adapters[ty]
	return exists
}
HasInverseAdapter returns true/false if giving type has inverse adapter registered.
package reflection
import (
	"errors"
	"reflect"
	"time"
)
var (
	ErrNoFieldWithTagFound = errors.New("field with tag name not found in struct")
)
type MapAdapter func(Field) (interface{}, error)
func TimeMapper(layout string) MapAdapter {
	return func(f Field) (interface{}, error) {
		if timeObj, ok := f.Value.Interface().(time.Time); ok {
			return timeObj.Format(layout), nil
		}
		if timeObj, ok := f.Value.Interface().(*time.Time); ok {
			return timeObj.Format(layout), nil
		}
		return nil, errors.New("not time value")
	}
}
type InverseMapAdapter func(Field, interface{}) (interface{}, error)
func TimeInverseMapper(layout string) InverseMapAdapter {
	return func(f Field, val interface{}) (interface{}, error) {
		if _, ok := val.(time.Time); ok {
			return val, nil
		}
		if dtime, ok := val.(*time.Time); ok {
			return *dtime, nil
		}
		if formatted, ok := val.(string); ok {
			return time.Parse(layout, formatted)
		}
		return nil, errors.New("non supported time type")
	}
}
type Mapper interface {
	MapTo(string, interface{}, map[string]interface{}) error
	MapFrom(string, interface{}) (map[string]interface{}, error)
}
type StructMapper struct {
	adapters  map[reflect.Type]MapAdapter
	iadapters map[reflect.Type]InverseMapAdapter
}
func NewStructMapper() *StructMapper {
	return &StructMapper{
		adapters:  make(map[reflect.Type]MapAdapter),
		iadapters: make(map[reflect.Type]InverseMapAdapter),
	}
}
func (sm *StructMapper) MapTo(tag string, target interface{}, data map[string]interface{}) error {
	fields, err := GetTagFields(target, tag, true)
	if err != nil {
		return err
	}
	if len(fields) == 0 {
		return ErrNoFieldWithTagFound
	}
	targetValue := reflect.ValueOf(target)
	if targetValue.Kind() == reflect.Ptr {
		targetValue = targetValue.Elem()
	}
	for _, field := range fields {
		value, ok := data[field.Tag]
		if !ok {
			value, ok = data[field.Name]
			if !ok {
				value, ok = data[field.NameLC]
				if !ok {
					continue
				}
			}
		}
		fieldTarget := targetValue.Field(field.Index)
		if !fieldTarget.CanSet() {
			continue
		}
		if iadapter, ok := sm.iadapters[field.Type]; ok {
			converted, err := iadapter(field, value)
			if err != nil {
				return err
			}
			fieldTarget.Set(reflect.ValueOf(converted))
			continue
		}
		if innerMap, ok := value.(map[string]interface{}); ok {
			if field.Type.Kind() == reflect.Struct {
				if err := sm.MapTo(tag, fieldTarget.Addr().Interface(), innerMap); err != nil {
					return err
				}
				continue
			}
		}
		fieldTarget.Set(reflect.ValueOf(value))
	}
	return nil
}
func (sm *StructMapper) MapFrom(tag string, target interface{}) (map[string]interface{}, error) {
	data := make(map[string]interface{})
	fields, err := GetTagFields(target, tag, true)
	if err != nil {
		return data, err
	}
	if len(fields) == 0 {
		return data, nil
	}
	for _, field := range fields {
		if !field.Value.CanInterface() {
			continue
		}
		if adapter, ok := sm.adapters[field.Type]; ok {
			res, err := adapter(field)
			if err != nil {
				return data, err
			}
			if field.Tag == "" {
				data[field.Name] = res
			} else {
				data[field.Tag] = res
			}
			continue
		}
		if field.Type.Kind() == reflect.Struct {
			mapped, err := sm.MapFrom(tag, field.Value.Interface())
			if err != nil {
				return data, err
			}
			if field.Tag == "" {
				data[field.Name] = mapped
			} else {
				data[field.Tag] = mapped
			}
			continue
		}
		if field.Tag == "" {
			data[field.Name] = field.Value.Interface()
		} else {
			data[field.Tag] = field.Value.Interface()
		}
	}
	return data, nil
}