// createMapResponse is a helper for generating a response value from
// a value of type map.
func createMapResponse(value reflect.Value, options objx.Map, constructor func(interface{}, interface{}) interface{}, domain string) interface{} {
	response := reflect.MakeMap(value.Type())
	for _, key := range value.MapKeys() {
		var elementOptions objx.Map
		keyStr := key.Interface().(string)
		if options != nil {
			var elementOptionsValue *objx.Value
			if options.Has(keyStr) {
				elementOptionsValue = options.Get(keyStr)
			} else if options.Has("*") {
				elementOptionsValue = options.Get("*")
			}
			if elementOptionsValue.IsMSI() {
				elementOptions = objx.Map(elementOptionsValue.MSI())
			} else if elementOptionsValue.IsObjxMap() {
				elementOptions = elementOptionsValue.ObjxMap()
			} else {
				panic("Don't know what to do with option")
			}
		}
		itemResponse := createResponseValue(value.MapIndex(key), elementOptions, constructor, domain)
		response.SetMapIndex(key, reflect.ValueOf(itemResponse))
	}
	return response.Interface()
}
// createStructResponse is a helper for generating a response value
// from a value of type struct.
func createStructResponse(value reflect.Value, options objx.Map, constructor func(interface{}, interface{}) interface{}, domain string) interface{} {
	structType := value.Type()

	// Support "database/sql".Null* types, and any other types
	// matching that structure
	if v, err := createNullableDbResponse(value, structType); err == nil {
		return v
	}

	response := make(objx.Map)

	for i := 0; i < value.NumField(); i++ {
		fieldType := structType.Field(i)
		fieldValue := value.Field(i)

		if fieldType.Anonymous {
			embeddedResponse := CreateResponse(fieldValue.Interface(), options, constructor, domain).(objx.Map)
			for key, value := range embeddedResponse {
				// Don't overwrite values from the base struct
				if _, ok := response[key]; !ok {
					response[key] = value
				}
			}
		} else if unicode.IsUpper(rune(fieldType.Name[0])) {
			name := ResponseTag(fieldType)
			switch name {
			case "-":
				continue
			default:
				var subOptions objx.Map
				if options != nil && (options.Has(name) || options.Has("*")) {
					var subOptionsValue *objx.Value
					if options.Has(name) {
						subOptionsValue = options.Get(name)
					} else {
						subOptionsValue = options.Get("*")
					}
					if subOptionsValue.IsMSI() {
						subOptions = objx.Map(subOptionsValue.MSI())
					} else if subOptionsValue.IsObjxMap() {
						subOptions = subOptionsValue.ObjxMap()
					} else {
						panic("Don't know what to do with option")
					}
				}
				response[name] = createResponseValue(fieldValue, subOptions, constructor, domain)
			}
		}
	}
	return response
}