Ejemplo n.º 1
0
/**
 *	创建结构体递归遍历子字段操作
 *
 *	@param structV			递归操作字段
 *	@param joinFieldName	字段连接名
 *	@param arraySizeMap		解析后的集合数量设值map
 */
func parampackNewStructFindFiled(structV reflect.Value, joinFieldName string, arraySizeMap map[string]int) {
	structV = reflect.Indirect(structV)
	if reflect.Struct != structV.Kind() {
		return
	}

	//	遍历结构字段寻找需要初始化的slice
	filedCount := structV.NumField()
	for i := 0; i < filedCount; i++ {
		childField := structV.Field(i)
		childFieldType := childField.Type()
		childFieldName := structV.Type().Field(i).Name

		if !childField.CanSet() {
			continue
		}

		if 0 != len(joinFieldName) && '.' != joinFieldName[len(joinFieldName)-1] {
			joinFieldName += "."
		}

		if reflect.Ptr == childFieldType.Kind() && childField.IsNil() {
			//	初始化子结构指针的操作
			childField.Set(reflect.New(childField.Type().Elem()))
		}

		switch reflect.Indirect(childField).Kind() {
		case reflect.Struct:
			if !parampackFilterParamPackStructType(childField.Type()) {
				parampackNewStructFindFiled(childField, joinFieldName+childFieldName, arraySizeMap)
			}
		case reflect.Slice:

			tempJoinName := joinFieldName + childFieldName

			if sliceSize, ok := arraySizeMap[strings.ToLower(tempJoinName)]; ok {

				valueElem := reflect.Indirect(childField)
				valueElem.Set(reflect.MakeSlice(valueElem.Type(), sliceSize, sliceSize))

				//	继续执行集合子元素的遍历
				if !parampackFilterParamPackStructType(valueElem.Type()) {
					for j := 0; j < sliceSize; j++ {
						childIndex := valueElem.Index(j)

						if reflect.Ptr == childIndex.Kind() && childIndex.IsNil() {
							//	初始化子元素指针的操作
							childIndex.Set(reflect.New(childIndex.Type().Elem()))
						}

						//	当前由于是数组类型,所以传递连接名的时候加上"[index]"下标往下进行操作
						tempJoinName = joinFieldName + childFieldName + "[" + strconv.Itoa(j) + "]"

						parampackNewStructFindFiled(childIndex, tempJoinName, arraySizeMap)
					}
				}
			}
		}
	}
}
Ejemplo n.º 2
0
/**
 *	针对字段进行设值
 *
 *	@param fieldValue		字段反射对象
 *	@param fieldName		字段名,以便递归寻找下个设值字段
 *	@param fieldSplitName	字段名分割集合,以"."进行分割,主要是为了递归子字段进行拼接传递
 *	@param value			设置值
 */
func parampackSetFieldValue(fieldValue reflect.Value, fieldName string, fieldSplitName []string, value interface{}) {

	if fieldValue.IsValid() {

		//	为递归下一个参数做准备,保留后面的参数名(tag.TagName)
		isRec := false
		joinLaterFieldName := ""
		if 1 < len(fieldSplitName) {
			joinLaterFieldName = strings.Join(fieldSplitName[1:], ".")
			isRec = true
			//	进入这里表明还需要进行一次字段查询,所以需要进行递归操作,直到截取到最后一位的参数名标识(TagName)
		}

		switch fieldValue.Kind() {
		case reflect.Ptr:

			if fieldValue.IsNil() {
				fieldValue.Set(reflect.New(fieldValue.Type().Elem()))
			}

			//	指针与非指针区分开,主要是在进行参数设值的时候对应与设置值相同的类型,减免指针的过多操作。
			switch fieldValue.Elem().Kind() {
			case reflect.Struct:
				if isRec && !parampackFilterParamPackStructType(fieldValue.Type().Elem()) {
					parampackSetStructFieldValue(fieldValue, joinLaterFieldName, value)
				} else {
					parampackSetParamValue(fieldValue, fieldName, value)
				}

			case reflect.Slice:
				//	如果属于切片类型,传递fieldName主要是在操作一遍集合元素的赋值,因为不是结构类型无需再向下查找
				parampackSetStructFieldValue(fieldValue, fieldName, value)
			default:
				parampackSetParamValue(fieldValue, fieldName, value)
			}

		case reflect.Struct:

			if isRec && !parampackFilterParamPackStructType(fieldValue.Type()) {
				parampackSetStructFieldValue(fieldValue, joinLaterFieldName, value)
			} else {
				//	如果检测的是系统或则非用户定义的struct就可以直接赋值了,赋值那里已经做了匹配类型才进行赋值的处理
				parampackSetParamValue(fieldValue, fieldName, value)
			}
		case reflect.Slice:
			parampackSetStructFieldValue(fieldValue, fieldName, value)
		default:
			parampackSetParamValue(fieldValue, fieldName, value)
		}

	}
}
Ejemplo n.º 3
0
/**
 *	根据url和form参数信息创建一个struct体,如果存在集合结构会根据form参数信息make分配切片大小。
 *
 *	@param structType 需要操作的的结构
 *	@param urlValues  url或form请求参数(主要为了操作slice的创建元素)
 *	@return	返回创建好的函数反射对象信息(指针类型的)
 */
func parampackNewStructPtr(structType reflect.Type, urlValues url.Values) reflect.Value {
	//	考虑到结构内包含指针,如果不进行new的话直接(.)会爆出空指针异常,所以这里需要遍历每个对象

	if structType.Kind() != reflect.Struct {
		return reflect.Zero(structType)
	}

	structValue := reflect.New(structType)

	if 0 == len(urlValues) {
		return structValue
	}

	//	begin 分析数组	TODO 需要调整集合下的集合 type[0].tmpe[0]
	arraySizeMap := make(map[string]int) //	key = jsonfiledname ,value = array size

	for k, _ := range urlValues {
		//	存储(oneUser.hobbys.names)操作的连接名 如果存在集合则存储为key
		tempJoinName := ""

		fields := strings.Split(k, ".")

		for _, field := range fields {

			fieldLower := strings.ToLower(field)

			strIndex := _arrayTagRex.FindString(fieldLower)
			if 0 != len(strIndex) {
				intIndex, err := strconv.Atoi(strIndex[1 : len(strIndex)-1])
				if nil == err {

					//	这里为key做准备
					tempJoinName += fieldLower[:len(fieldLower)-len(strIndex)]

					//	由于下标是从0开始计算,所以需要+1作为 array size
					intIndex += 1

					if sizeIndex, ok := arraySizeMap[tempJoinName]; ok {

						if sizeIndex < intIndex {
							arraySizeMap[tempJoinName] = intIndex
						}
					} else {
						arraySizeMap[tempJoinName] = intIndex
					}

					//	由于可能存在数组下还存在集合(temp[0].temp2[0]),所以继续累加"[index]."继续执行。
					tempJoinName += strIndex + "."
				} else {
					//	进入到这部基本上是获取的 "[ 错误下标 ]" 才导致的,所欲当没有下标出现,继续累加
					tempJoinName += fieldLower + "."
				}
			} else {
				tempJoinName += fieldLower + "."
			}

		}
	}
	//	end 分析数组

	//	执行递归子字段操作
	parampackNewStructFindFiled(structValue, "", arraySizeMap)

	return structValue
}