type Base struct { Field int F2 string F3 float64 } type Type1 struct { Base Field string }
d := Type1{ Base: Base{ Field: 123, F2: "Base_F2", F3: 0.45, }, Field: "UP_LOAD", } bytes, _ := json.Marshal(d) fmt.Println(string(bytes)) d2 := Type1{} _ = json.Unmarshal(bytes, &d2) fmt.Printf("%#v", d2)
{"F2":"Base_F2","F3":0.45,"Field":"UP_LOAD"} util.Type1{Base:util.Base{Field:0, F2:"Base_F2", F3:0.45}, Field:"UP_LOAD"}
switch t.Kind() { case reflect.Bool: return boolEncoder case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return intEncoder case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return uintEncoder case reflect.Float32: return float32Encoder case reflect.Float64: return float64Encoder case reflect.String: return stringEncoder case reflect.Interface: return interfaceEncoder case reflect.Struct: return newStructEncoder(t) case reflect.Map: return newMapEncoder(t) case reflect.Slice: return newSliceEncoder(t) case reflect.Array: return newArrayEncoder(t) case reflect.Ptr: return newPtrEncoder(t) default: return unsupportedTypeEncoder }
func (se structEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) { next := byte(‘{‘) FieldLoop: // 遍历每个字段,字段进行递归编码 for i := range se.fields.list { f := &se.fields.list[i] // Find the nested struct field by following f.index. // 对于内嵌的结构体,f.index有多个,比方说对于上面的Type1的Base.Field该字段来说 // index值将是[0, 0] fv := v for _, i := range f.index { if fv.Kind() == reflect.Ptr { if fv.IsNil() { continue FieldLoop } fv = fv.Elem() } fv = fv.Field(i) } if f.omitEmpty && isEmptyValue(fv) { continue } e.WriteByte(next) next = ‘,‘ if opts.escapeHTML { e.WriteString(f.nameEscHTML) } else { e.WriteString(f.nameNonEsc) // 写入名称,格式是`"name":` } opts.quoted = f.quoted f.encoder(e, fv, opts) // 使用字段的编码器进行编码 } if next == ‘{‘ { e.WriteString("{}") // 空结构 } else { e.WriteByte(‘}‘) } }
// typeFields returns a list of fields that JSON should recognize for the given type. // The algorithm is breadth-first search over the set of structs to include - the top struct // and then any reachable anonymous structs. func typeFields(t reflect.Type) structFields { // Anonymous fields to explore at the current level and the next. current := []field{} next := []field{{typ: t}} // Count of queued names for current level and the next. var count, nextCount map[reflect.Type]int // Types already visited at an earlier level. visited := map[reflect.Type]bool{} // Fields found. var fields []field // Buffer to run HTMLEscape on field names. var nameEscBuf bytes.Buffer for len(next) > 0 { current, next = next, current[:0] count, nextCount = nextCount, map[reflect.Type]int{} for _, f := range current { if visited[f.typ] { continue } visited[f.typ] = true // Scan f.typ for fields to include. for i := 0; i < f.typ.NumField(); i++ { sf := f.typ.Field(i) isUnexported := sf.PkgPath != "" if sf.Anonymous { t := sf.Type if t.Kind() == reflect.Ptr { t = t.Elem() } if isUnexported && t.Kind() != reflect.Struct { // Ignore embedded fields of unexported non-struct types. continue } // Do not ignore embedded fields of unexported struct types // since they may have exported fields. } else if isUnexported { // Ignore unexported non-embedded fields. continue } // 解析tag,如果是"-",该字段直接忽略,检查需要开启string选项 ... // Record found field and index sequence. if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct { // 初始化field的属性 tagged := name != "" if name == "" { name = sf.Name } field := field{ name: name, tag: tagged, ... fields = append(fields, field) if count[f.typ] > 1 { // If there were multiple instances, add a second, // so that the annihilation code will see a duplicate. // It only cares about the distinction between 1 or 2, // so don‘t bother generating any more copies. fields = append(fields, fields[len(fields)-1]) } continue } // Record new anonymous struct to explore in next round. nextCount[ft]++ if nextCount[ft] == 1 { next = append(next, field{name: ft.Name(), index: index, typ: ft}) } } } } //按照name, len(index)(嵌套struct的深度), tag进行排序 // 为了之后方便过滤掉有重复名称的属性 sort.Slice(fields, func(i, j int) bool { x := fields // sort field by name, breaking ties with depth, then // breaking ties with "name came from json tag", then // breaking ties with index sequence. if x[i].name != x[j].name { return x[i].name < x[j].name } if len(x[i].index) != len(x[j].index) { return len(x[i].index) < len(x[j].index) } if x[i].tag != x[j].tag { return x[i].tag } return byIndex(x).Less(i, j) }) out := fields[:0] for advance, i := 0, 0; i < len(fields); i += advance { // One iteration per name. // Find the sequence of fields with the name of this first field. .... } fields = out sort.Sort(byIndex(fields)) for i := range fields { f := &fields[i] f.encoder = typeEncoder(typeByIndex(t, f.index)) // 递归遍历每个field的编码器 } ... return structFields{fields, nameIndex} }
原文:https://www.cnblogs.com/RayFong/p/13660729.html