schemaForMessageWithVisited recurses into nested message fields while guarding against cycles. The descriptor full-name is the visit key — well-known types like google.protobuf.Value reference themselves via repeated-Value lists, which would stack-overflow without this. On a re-visit we emit an opa
(md protoreflect.MessageDescriptor, visited map[protoreflect.FullName]struct{})
| 33 | // type (it can pass any JSON object; the server validates at the proto |
| 34 | // layer via protovalidate). |
| 35 | func schemaForMessageWithVisited(md protoreflect.MessageDescriptor, visited map[protoreflect.FullName]struct{}) jsonSchema { |
| 36 | if _, seen := visited[md.FullName()]; seen { |
| 37 | return jsonSchema{Type: "object"} |
| 38 | } |
| 39 | visited[md.FullName()] = struct{}{} |
| 40 | defer delete(visited, md.FullName()) |
| 41 | |
| 42 | root := jsonSchema{ |
| 43 | Type: "object", |
| 44 | Properties: map[string]jsonSchema{}, |
| 45 | } |
| 46 | fields := md.Fields() |
| 47 | for i := 0; i < fields.Len(); i++ { |
| 48 | f := fields.Get(i) |
| 49 | root.Properties[string(f.Name())] = schemaForField(f, visited) |
| 50 | } |
| 51 | return root |
| 52 | } |
| 53 | |
| 54 | func schemaForField(f protoreflect.FieldDescriptor, visited map[protoreflect.FullName]struct{}) jsonSchema { |
| 55 | // repeated → JSON array |
no test coverage detected