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