(t reflect.Type)
| 210 | } |
| 211 | |
| 212 | func (e *encoder) newStructTypeEncoder(t reflect.Type) encoderFunc { |
| 213 | if t.Implements(reflect.TypeOf((*param.Optional)(nil)).Elem()) { |
| 214 | return e.newRichFieldTypeEncoder(t) |
| 215 | } |
| 216 | |
| 217 | for i := 0; i < t.NumField(); i++ { |
| 218 | if t.Field(i).Type == paramUnionType && t.Field(i).Anonymous { |
| 219 | return e.newStructUnionTypeEncoder(t) |
| 220 | } |
| 221 | } |
| 222 | |
| 223 | encoderFields := []encoderField{} |
| 224 | extraEncoder := (*encoderField)(nil) |
| 225 | |
| 226 | // This helper allows us to recursively collect field encoders into a flat |
| 227 | // array. The parameter `index` keeps track of the access patterns necessary |
| 228 | // to get to some field. |
| 229 | var collectEncoderFields func(r reflect.Type, index []int) |
| 230 | collectEncoderFields = func(r reflect.Type, index []int) { |
| 231 | for i := 0; i < r.NumField(); i++ { |
| 232 | idx := append(index, i) |
| 233 | field := t.FieldByIndex(idx) |
| 234 | if !field.IsExported() { |
| 235 | continue |
| 236 | } |
| 237 | // If this is an embedded struct, traverse one level deeper to extract |
| 238 | // the field and get their encoders as well. |
| 239 | if field.Anonymous { |
| 240 | collectEncoderFields(field.Type, idx) |
| 241 | continue |
| 242 | } |
| 243 | // If json tag is not present, then we skip, which is intentionally |
| 244 | // different behavior from the stdlib. |
| 245 | ptag, ok := parseFormStructTag(field) |
| 246 | if !ok { |
| 247 | continue |
| 248 | } |
| 249 | // We only want to support unexported field if they're tagged with |
| 250 | // `extras` because that field shouldn't be part of the public API. We |
| 251 | // also want to only keep the top level extras |
| 252 | if ptag.extras && len(index) == 0 { |
| 253 | extraEncoder = &encoderField{ptag, e.typeEncoder(field.Type.Elem()), idx} |
| 254 | continue |
| 255 | } |
| 256 | if ptag.name == "-" || ptag.name == "" { |
| 257 | continue |
| 258 | } |
| 259 | |
| 260 | dateFormat, ok := parseFormatStructTag(field) |
| 261 | oldFormat := e.dateFormat |
| 262 | if ok { |
| 263 | switch dateFormat { |
| 264 | case "date-time": |
| 265 | e.dateFormat = time.RFC3339 |
| 266 | case "date": |
| 267 | e.dateFormat = "2006-01-02" |
| 268 | } |
| 269 | } |
no test coverage detected