示例#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)
					}
				}
			}
		}
	}
}
示例#2
0
/**
 *  private marshal
 */
func marshal(v reflect.Value, nullTag, boolTag string, buf *bytes.Buffer) error {
	var err error

	switch v.Kind() {
	case reflect.Bool:
		boolTrue := "true"
		boolFalse := "false"
		if "" != boolTag {
			bs := strings.Split(boolTag, "|")
			if 2 == len(bs) {
				boolTrue = bs[0]
				boolFalse = bs[1]
			}
		}
		bv := v.Bool()
		if bv {
			buf.WriteString(boolTrue)
		} else {
			buf.WriteString(boolFalse)
		}
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		b := strconv.AppendInt(scratch[:0], v.Int(), 10)
		buf.Write(b)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		b := strconv.AppendUint(scratch[:0], v.Uint(), 10)
		buf.Write(b)
	case reflect.Float32, reflect.Float64:
		f := v.Float()
		if math.IsInf(f, 0) || math.IsNaN(f) {
			err = errors.New(strconv.FormatFloat(f, 'g', -1, v.Type().Bits()))
		}
		b := strconv.AppendFloat(scratch[:0], f, 'g', -1, v.Type().Bits())
		buf.Write(b)
	case reflect.String:
		if 0 == v.Len() {
			buf.WriteString("\"\"")
		} else {
			buf.WriteByte('"')
			_, err = escapeString(buf, v.String())
			buf.WriteByte('"')
		}

	case reflect.Struct:
		vt := v.Type()
		numTField := vt.NumField()

		if 0 == numTField {
			if "" != nullTag && 0 < buf.Len() {
				buf.WriteString(nullTag)
			}
			break
		}

		if vt.Implements(textMarshalerType) {
			imt := v.Interface().(encoding.TextMarshaler)
			mt, e := imt.MarshalText()
			if nil != e {
				err = e
			} else {
				buf.WriteByte('"')
				buf.Write(mt)
				buf.WriteByte('"')
			}
			break
		}

		buf.WriteByte('{')
		first := true

		for i := 0; i < numTField; i++ {
			childFieldT := vt.Field(i)
			childFieldV := v.Field(i)

			if "" == nullTag && SFReflectUtil.IsNullValue(childFieldV) {
				continue
			}

			keyName := childFieldT.Tag.Get("json")
			if 0 == len(keyName) {
				keyName = childFieldT.Name
			} else if "-" == keyName {
				continue
			}

			if first {
				first = false
			} else {
				buf.WriteByte(',')
			}

			buf.WriteString("\"" + keyName + "\"")
			buf.WriteByte(':')
			marshal(childFieldV, nullTag, boolTag, buf)
		}

		buf.WriteByte('}')
	case reflect.Map:
		if v.Type().Key().Kind() != reflect.String {
			err = errors.New("json: unsupported type: " + v.Type().String())
			break
		}
		if 0 == v.Len() {
			if "" != nullTag && 0 < buf.Len() {
				buf.WriteString(nullTag)
			}
			break
		}

		buf.WriteByte('{')
		first := true
		for _, k := range v.MapKeys() {
			kv := v.MapIndex(k)

			if "" == nullTag && SFReflectUtil.IsNullValue(kv) {
				continue
			}

			if first {
				first = false
			} else {
				buf.WriteByte(',')
			}
			buf.WriteString("\"" + k.String() + "\"")
			buf.WriteByte(':')
			marshal(kv, nullTag, boolTag, buf)
		}
		buf.WriteByte('}')

	case reflect.Array, reflect.Slice:
		if 0 == v.Len() {
			if "" != nullTag && 0 < buf.Len() {
				buf.WriteString(nullTag)
			}
			break
		}
		if v.Type().Elem().Kind() == reflect.Uint8 {

			s := v.Bytes()
			buf.WriteByte('"')
			if len(s) < 1024 {
				// for small buffers, using Encode directly is much faster.
				dst := make([]byte, base64.StdEncoding.EncodedLen(len(s)))
				base64.StdEncoding.Encode(dst, s)
				buf.Write(dst)
			} else {
				// for large buffers, avoid unnecessary extra temporary
				// buffer space.
				enc := base64.NewEncoder(base64.StdEncoding, buf)
				enc.Write(s)
				enc.Close()
			}
			buf.WriteByte('"')

		} else {
			buf.WriteByte('[')
			first := true
			count := v.Len()
			for i := 0; i < count; i++ {
				v2 := v.Index(i)
				if "" == nullTag && SFReflectUtil.IsNullValue(v2) {
					continue
				}
				if first {
					first = false
				} else {
					buf.WriteByte(',')
				}
				marshal(v2, nullTag, boolTag, buf)
			}
			buf.WriteByte(']')
		}
	case reflect.Interface, reflect.Ptr:
		if v.IsNil() {
			if "" != nullTag {
				buf.WriteString(nullTag)
			}
			break
		}
		marshal(v.Elem(), nullTag, boolTag, buf)
	default:
	}

	return err
}