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. typeFields should be an internal detail, but widely used packages access it using li
(t reflect.Type)
| 1142 | // |
| 1143 | //go:linkname typeFields |
| 1144 | func typeFields(t reflect.Type) structFields { |
| 1145 | // Anonymous fields to explore at the current level and the next. |
| 1146 | current := []field{} |
| 1147 | next := []field{{typ: t}} |
| 1148 | |
| 1149 | // Count of queued names for current level and the next. |
| 1150 | var count, nextCount map[reflect.Type]int |
| 1151 | |
| 1152 | // Types already visited at an earlier level. |
| 1153 | visited := map[reflect.Type]bool{} |
| 1154 | |
| 1155 | // Fields found. |
| 1156 | var fields []field |
| 1157 | |
| 1158 | // Buffer to run appendHTMLEscape on field names. |
| 1159 | var nameEscBuf []byte |
| 1160 | |
| 1161 | for len(next) > 0 { |
| 1162 | current, next = next, current[:0] |
| 1163 | count, nextCount = nextCount, map[reflect.Type]int{} |
| 1164 | |
| 1165 | for _, f := range current { |
| 1166 | if visited[f.typ] { |
| 1167 | continue |
| 1168 | } |
| 1169 | visited[f.typ] = true |
| 1170 | |
| 1171 | // Scan f.typ for fields to include. |
| 1172 | for i := 0; i < f.typ.NumField(); i++ { |
| 1173 | sf := f.typ.Field(i) |
| 1174 | if sf.Anonymous { |
| 1175 | t := sf.Type |
| 1176 | if t.Kind() == reflect.Pointer { |
| 1177 | t = t.Elem() |
| 1178 | } |
| 1179 | if !sf.IsExported() && t.Kind() != reflect.Struct { |
| 1180 | // Ignore embedded fields of unexported non-struct types. |
| 1181 | continue |
| 1182 | } |
| 1183 | // Do not ignore embedded fields of unexported struct types |
| 1184 | // since they may have exported fields. |
| 1185 | } else if !sf.IsExported() { |
| 1186 | // Ignore unexported non-embedded fields. |
| 1187 | continue |
| 1188 | } |
| 1189 | tag := sf.Tag.Get("json") |
| 1190 | if tag == "-" { |
| 1191 | continue |
| 1192 | } |
| 1193 | name, opts := parseTag(tag) |
| 1194 | if !isValidTag(name) { |
| 1195 | name = "" |
| 1196 | } |
| 1197 | index := make([]int, len(f.index)+1) |
| 1198 | copy(index, f.index) |
| 1199 | index[len(f.index)] = i |
| 1200 | |
| 1201 | ft := sf.Type |
no test coverage detected
searching dependent graphs…