Open srilman opened 5 months ago
And from my understanding, to change this behavior, we just need to change function getFields
in file huma/schema.go
:
func getFields(typ reflect.Type, visited map[reflect.Type]struct{}) []fieldInfo {
fields := make([]fieldInfo, 0, typ.NumField())
var embedded []reflect.StructField
if _, ok := visited[typ]; ok {
return fields
}
visited[typ] = struct{}{}
for i := 0; i < typ.NumField(); i++ {
f := typ.Field(i)
if !f.IsExported() {
continue
}
if f.Anonymous {
embedded = append(embedded, f)
continue
}
fields = append(fields, fieldInfo{typ, f})
}
for _, f := range embedded {
newTyp := f.Type
for newTyp.Kind() == reflect.Ptr {
newTyp = newTyp.Elem()
}
if newTyp.Kind() == reflect.Struct {
fields = append(fields, getFields(newTyp, visited)...)
}
}
return fields
}
All to change is move this snippet:
if !f.IsExported() {
continue
}
underneath the if statement if f.Anonymous {
@srilman thanks for the issue! I believe this was done on purpose because Go can't use reflection to access private fields from other packages, so it would be inconsistent to allow access from within your package but disallow it from imported packages. I can dig a bit deeper just to confirm this is the case with embedded private fields.
Currently in the process of building some of the more complex schemas for an OpenAPI-based API and running into some new issues. I have an example that looks something like this:
In models.go
In main.go:
The output only contains the outer field
Changing
commonElems
toCommonElems
so the embedded struct is exported, the output contains both expected fields:Unfortunately, unlike the example, the structs V1 and V2 are located in another library that I don't have easy control over. But furthermore, I think the second output should be the default, since in Go we can still access exported fields inside of unexported embedded structs (as seen in the code example) and JSON marshalling/unmarshalling works the same. What are others thoughts?