/** * 针对字段进行设值 * * @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) } } }
/** * 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 }