#2 - change to micro-proto/openapi
This commit is contained in:
parent
e207117ba4
commit
8b6c5049b1
@ -240,7 +240,7 @@ func newHTTPTask(ctx context.Context, l logger.Logger, m meter.Meter, check stri
|
|||||||
// client.WithContentType("application/json"),
|
// client.WithContentType("application/json"),
|
||||||
}
|
}
|
||||||
|
|
||||||
msg, err := swaggerSet.GetMessage(task.HTTP.Addr, svc, task.HTTP.Method, "POST")
|
msg, err := swaggerSet.GetMessage(task.HTTP.Addr, svc, task.HTTP.Method)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Error(ctx, "failed to get message from swagger spec", err)
|
l.Error(ctx, "failed to get message from swagger spec", err)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
3
go.mod
3
go.mod
@ -5,7 +5,6 @@ go 1.23.3
|
|||||||
require (
|
require (
|
||||||
github.com/getkin/kin-openapi v0.128.0
|
github.com/getkin/kin-openapi v0.128.0
|
||||||
github.com/go-co-op/gocron/v2 v2.12.3
|
github.com/go-co-op/gocron/v2 v2.12.3
|
||||||
github.com/google/gnostic v0.7.0
|
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/ompluscator/dynamic-struct v1.4.0
|
github.com/ompluscator/dynamic-struct v1.4.0
|
||||||
github.com/stretchr/testify v1.9.0
|
github.com/stretchr/testify v1.9.0
|
||||||
@ -17,6 +16,7 @@ require (
|
|||||||
go.unistack.org/micro-codec-yaml/v3 v3.10.2
|
go.unistack.org/micro-codec-yaml/v3 v3.10.2
|
||||||
go.unistack.org/micro-meter-victoriametrics/v3 v3.8.9
|
go.unistack.org/micro-meter-victoriametrics/v3 v3.8.9
|
||||||
go.unistack.org/micro-proto/v3 v3.4.1
|
go.unistack.org/micro-proto/v3 v3.4.1
|
||||||
|
go.unistack.org/micro-proto/v4 v4.1.0
|
||||||
go.unistack.org/micro-server-http/v3 v3.11.34
|
go.unistack.org/micro-server-http/v3 v3.11.34
|
||||||
go.unistack.org/micro/v3 v3.10.100
|
go.unistack.org/micro/v3 v3.10.100
|
||||||
google.golang.org/protobuf v1.35.2
|
google.golang.org/protobuf v1.35.2
|
||||||
@ -26,6 +26,7 @@ require (
|
|||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||||
github.com/go-openapi/swag v0.23.0 // indirect
|
github.com/go-openapi/swag v0.23.0 // indirect
|
||||||
|
github.com/google/gnostic v0.7.0 // indirect
|
||||||
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
|
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
|
||||||
github.com/invopop/yaml v0.3.1 // indirect
|
github.com/invopop/yaml v0.3.1 // indirect
|
||||||
github.com/jonboulle/clockwork v0.4.0 // indirect
|
github.com/jonboulle/clockwork v0.4.0 // indirect
|
||||||
|
2
go.sum
2
go.sum
@ -936,6 +936,8 @@ go.unistack.org/micro-meter-victoriametrics/v3 v3.8.9 h1:ZXCS0eFiSdvcFYxpxV2Q77g
|
|||||||
go.unistack.org/micro-meter-victoriametrics/v3 v3.8.9/go.mod h1:xODJQ0Nu/F8k34D/z2ITL91OskI/C674XCkugAxmc3Q=
|
go.unistack.org/micro-meter-victoriametrics/v3 v3.8.9/go.mod h1:xODJQ0Nu/F8k34D/z2ITL91OskI/C674XCkugAxmc3Q=
|
||||||
go.unistack.org/micro-proto/v3 v3.4.1 h1:UTjLSRz2YZuaHk9iSlVqqsA50JQNAEK2ZFboGqtEa9Q=
|
go.unistack.org/micro-proto/v3 v3.4.1 h1:UTjLSRz2YZuaHk9iSlVqqsA50JQNAEK2ZFboGqtEa9Q=
|
||||||
go.unistack.org/micro-proto/v3 v3.4.1/go.mod h1:okx/cnOhzuCX0ggl/vToatbCupi0O44diiiLLsZ93Zo=
|
go.unistack.org/micro-proto/v3 v3.4.1/go.mod h1:okx/cnOhzuCX0ggl/vToatbCupi0O44diiiLLsZ93Zo=
|
||||||
|
go.unistack.org/micro-proto/v4 v4.1.0 h1:qPwL2n/oqh9RE3RTTDgt28XK3QzV597VugQPaw9lKUk=
|
||||||
|
go.unistack.org/micro-proto/v4 v4.1.0/go.mod h1:ArmK7o+uFvxSY3dbJhKBBX4Pm1rhWdLEFf3LxBrMtec=
|
||||||
go.unistack.org/micro-server-http/v3 v3.11.34 h1:Cu44/IWyTBa0I1LIt8TZu/z130uDs2t/OZJwV5H5NX0=
|
go.unistack.org/micro-server-http/v3 v3.11.34 h1:Cu44/IWyTBa0I1LIt8TZu/z130uDs2t/OZJwV5H5NX0=
|
||||||
go.unistack.org/micro-server-http/v3 v3.11.34/go.mod h1:3hlTQj3e6HQziJa2Coz/BwvVbt3oRejOevyAPUCuBEk=
|
go.unistack.org/micro-server-http/v3 v3.11.34/go.mod h1:3hlTQj3e6HQziJa2Coz/BwvVbt3oRejOevyAPUCuBEk=
|
||||||
go.unistack.org/micro/v3 v3.10.94/go.mod h1:erMgt3Bl7vQQ0e9UpQyR5NlLiZ9pKeEJ9+1tfYFaqUg=
|
go.unistack.org/micro/v3 v3.10.94/go.mod h1:erMgt3Bl7vQQ0e9UpQyR5NlLiZ9pKeEJ9+1tfYFaqUg=
|
||||||
|
@ -1,30 +1,29 @@
|
|||||||
package swaggerset
|
package swaggerset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/getkin/kin-openapi/openapi3"
|
openapi "go.unistack.org/micro-proto/v4/openapiv3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var errNotFound = errors.New("file descriptor not found")
|
var errNotFound = errors.New("file descriptor not found")
|
||||||
|
|
||||||
type SwaggerSet struct {
|
type SwaggerSet struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
files map[string]*openapi3.T
|
files map[string]*openapi.Document
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSwaggerSet() *SwaggerSet {
|
func NewSwaggerSet() *SwaggerSet {
|
||||||
return &SwaggerSet{
|
return &SwaggerSet{
|
||||||
mu: sync.Mutex{},
|
mu: sync.Mutex{},
|
||||||
files: make(map[string]*openapi3.T, 0),
|
files: make(map[string]*openapi.Document, 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *SwaggerSet) GetMessage(addr, svc, mth string, typereq string) (*Message, error) {
|
func (p *SwaggerSet) GetMessage(addr, svc, mth string) (*Message, error) {
|
||||||
if svc == "" || mth == "" || addr == "" || typereq == "" {
|
if svc == "" || mth == "" || addr == "" {
|
||||||
return nil, errors.New("addr or service name is empty")
|
return nil, errors.New("addr or service name is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,10 +31,34 @@ func (p *SwaggerSet) GetMessage(addr, svc, mth string, typereq string) (*Message
|
|||||||
doc := p.files[addr+"|"+svc]
|
doc := p.files[addr+"|"+svc]
|
||||||
p.mu.Unlock()
|
p.mu.Unlock()
|
||||||
|
|
||||||
pathItem := doc.Paths.Value(mth)
|
var reqParam, reqBody, rsp interface{}
|
||||||
reqParam, reqBody, rsp := handleOperation(typereq, pathItem.Get)
|
var typeReq string
|
||||||
|
for _, path := range doc.Paths.GetPath() {
|
||||||
|
if path.GetName() == mth {
|
||||||
|
if path.GetValue().GetGet() != nil {
|
||||||
|
typeReq = http.MethodGet
|
||||||
|
reqParam, reqBody, rsp = handleOperation(path.GetValue().GetGet(), doc)
|
||||||
|
}
|
||||||
|
if path.GetValue().GetPost() != nil {
|
||||||
|
typeReq = http.MethodPost
|
||||||
|
reqParam, reqBody, rsp = handleOperation(path.GetValue().GetPost(), doc)
|
||||||
|
}
|
||||||
|
if path.GetValue().GetDelete() != nil {
|
||||||
|
typeReq = http.MethodDelete
|
||||||
|
reqParam, reqBody, rsp = handleOperation(path.GetValue().GetDelete(), doc)
|
||||||
|
}
|
||||||
|
if path.GetValue().GetPatch() != nil {
|
||||||
|
typeReq = http.MethodPatch
|
||||||
|
reqParam, reqBody, rsp = handleOperation(path.GetValue().GetPatch(), doc)
|
||||||
|
}
|
||||||
|
if path.GetValue().GetPut() != nil {
|
||||||
|
typeReq = http.MethodPut
|
||||||
|
reqParam, reqBody, rsp = handleOperation(path.GetValue().GetPut(), doc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
msg := &Message{
|
msg := &Message{
|
||||||
Type: typereq,
|
Type: typeReq,
|
||||||
Request: httpRequest{
|
Request: httpRequest{
|
||||||
Header: reqParam,
|
Header: reqParam,
|
||||||
Body: reqBody,
|
Body: reqBody,
|
||||||
@ -47,18 +70,9 @@ func (p *SwaggerSet) GetMessage(addr, svc, mth string, typereq string) (*Message
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *SwaggerSet) AddSwaggerset(addr, svc string, data []byte) error {
|
func (p *SwaggerSet) AddSwaggerset(addr, svc string, data []byte) error {
|
||||||
ctx := context.Background()
|
doc, err := openapi.ParseDocument(data)
|
||||||
|
|
||||||
loader := openapi3.NewLoader()
|
|
||||||
loader.IsExternalRefsAllowed = true
|
|
||||||
|
|
||||||
doc, err := loader.LoadFromData(data)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to load data from buf: %w", err)
|
return err
|
||||||
}
|
|
||||||
|
|
||||||
if err = doc.Validate(ctx); err != nil {
|
|
||||||
return fmt.Errorf("failed to validate data from swagger: %w", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
|
@ -17,21 +17,17 @@ func TestSwaggerSet_1(t *testing.T) {
|
|||||||
err = s.AddSwaggerset("localhost:8080", "service", data)
|
err = s.AddSwaggerset("localhost:8080", "service", data)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
msgs, err := s.GetMessage(
|
msg, err := s.GetMessage(
|
||||||
"localhost:8080",
|
"localhost:8080",
|
||||||
"service",
|
"service",
|
||||||
"/domain-service/v1/push_mail/enabled",
|
"/domain-service/v1/push_mail/enabled",
|
||||||
[]string{"POST", "GET"})
|
"GET")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.NotNil(t, msgs.Msgs)
|
assert.NotNil(t, msg)
|
||||||
for _, msg := range msgs.Msgs {
|
req, err := json.Marshal(msg.Request)
|
||||||
reqParam, err := json.Marshal(msg.RequestParam)
|
assert.Nil(t, err)
|
||||||
assert.Nil(t, err)
|
rsp, err := json.Marshal(msg.Response)
|
||||||
reqBody, err := json.Marshal(msg.RequestBody)
|
assert.Nil(t, err)
|
||||||
assert.Nil(t, err)
|
fmt.Printf("JSON: type: %s, req: %s, rsp: %s \n", msg.Type, req, rsp)
|
||||||
rsp, err := json.Marshal(msg.Response)
|
fmt.Printf("Struct: type: %s, req: %+v, rsp: %+v \n", msg.Type, msg.Request, msg.Response)
|
||||||
assert.Nil(t, err)
|
|
||||||
fmt.Printf("JSON: type: %s, reqParam: %s, reqBody: %s, rsp: %s \n", msg.Type, reqParam, reqBody, rsp)
|
|
||||||
fmt.Printf("Struct: type: %s, reqParam: %+v, reqBody: %+v, rsp: %+v \n", msg.Type, msg.RequestParam, msg.RequestBody, msg.Response)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,8 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/getkin/kin-openapi/openapi3"
|
|
||||||
dynamicstruct "github.com/ompluscator/dynamic-struct"
|
dynamicstruct "github.com/ompluscator/dynamic-struct"
|
||||||
|
openapi "go.unistack.org/micro-proto/v4/openapiv3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Message struct {
|
type Message struct {
|
||||||
@ -20,17 +20,16 @@ type httpRequest struct {
|
|||||||
Body interface{}
|
Body interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleOperation(method string, operation *openapi3.Operation) (reqParam, reqBody, rsp interface{}) {
|
func handleOperation(operation *openapi.Operation, doc *openapi.Document) (reqParam, reqBody, rsp interface{}) {
|
||||||
fmt.Printf(" Method: %s\n", method)
|
|
||||||
|
|
||||||
// Обработка параметров (GET)
|
// Обработка параметров (GET)
|
||||||
if len(operation.Parameters) > 0 {
|
if len(operation.Parameters) > 0 {
|
||||||
paramsStruct := dynamicstruct.NewStruct()
|
paramsStruct := dynamicstruct.NewStruct()
|
||||||
for _, paramRef := range operation.Parameters {
|
for _, paramRef := range operation.Parameters {
|
||||||
param := paramRef.Value
|
var param *openapi.Parameter
|
||||||
|
param = paramRef.GetParameter()
|
||||||
fieldName := capitalize(param.Name)
|
fieldName := capitalize(param.Name)
|
||||||
jsonName := strings.ToLower(param.Name[:1]) + param.Name[1:]
|
jsonName := strings.ToLower(param.Name[:1]) + param.Name[1:]
|
||||||
goType := getGoType(param.Schema)
|
goType := getGoType(doc, param.Schema)
|
||||||
|
|
||||||
// В зависимости от того, где параметр находится (header, query, path, etc.), добавляем соответствующий тег
|
// В зависимости от того, где параметр находится (header, query, path, etc.), добавляем соответствующий тег
|
||||||
switch param.In {
|
switch param.In {
|
||||||
@ -47,9 +46,17 @@ func handleOperation(method string, operation *openapi3.Operation) (reqParam, re
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Обработка тела запроса (POST)
|
// Обработка тела запроса (POST)
|
||||||
if operation.RequestBody != nil {
|
if operation.GetRequestBody() != nil {
|
||||||
for _, content := range operation.RequestBody.Value.Content {
|
if operation.GetRequestBody().GetRequestBody() != nil {
|
||||||
bodyFields := buildDynamicStruct(content.Schema)
|
bodyFields := buildDynamicStruct(doc, operation.GetRequestBody().GetRequestBody().GetContent().GetAdditionalProperties()[0].GetValue().GetSchema())
|
||||||
|
bodyStruct := reflect.StructOf(bodyFields)
|
||||||
|
bodyInstance := reflect.New(bodyStruct).Interface()
|
||||||
|
// Получили тело запроса
|
||||||
|
reqBody = bodyInstance
|
||||||
|
}
|
||||||
|
if operation.GetRequestBody().GetReference() != nil {
|
||||||
|
schemOrRef := findReference(doc, operation.GetRequestBody().GetReference().GetXRef())
|
||||||
|
bodyFields := buildDynamicStruct(doc, schemOrRef)
|
||||||
bodyStruct := reflect.StructOf(bodyFields)
|
bodyStruct := reflect.StructOf(bodyFields)
|
||||||
bodyInstance := reflect.New(bodyStruct).Interface()
|
bodyInstance := reflect.New(bodyStruct).Interface()
|
||||||
// Получили тело запроса
|
// Получили тело запроса
|
||||||
@ -58,10 +65,19 @@ func handleOperation(method string, operation *openapi3.Operation) (reqParam, re
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Обработка ответов
|
// Обработка ответов
|
||||||
for status, response := range operation.Responses.Map() {
|
for _, rspOrRef := range operation.Responses.ResponseOrReference {
|
||||||
fmt.Printf(" Response Code: %s\n", status)
|
if rspOrRef.GetValue().GetResponse() != nil {
|
||||||
for _, content := range response.Value.Content {
|
for _, prop := range rspOrRef.Value.GetResponse().GetContent().GetAdditionalProperties() {
|
||||||
responseFields := buildDynamicStruct(content.Schema)
|
responseFields := buildDynamicStruct(doc, prop.GetValue().GetSchema())
|
||||||
|
responseStruct := reflect.StructOf(responseFields)
|
||||||
|
responseInstance := reflect.New(responseStruct).Interface()
|
||||||
|
// Получили структуру ответа
|
||||||
|
rsp = responseInstance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if rspOrRef.GetValue().GetReference() != nil {
|
||||||
|
schemaOrRef := findReference(doc, rspOrRef.GetValue().GetReference().GetXRef())
|
||||||
|
responseFields := buildDynamicStruct(doc, schemaOrRef)
|
||||||
responseStruct := reflect.StructOf(responseFields)
|
responseStruct := reflect.StructOf(responseFields)
|
||||||
responseInstance := reflect.New(responseStruct).Interface()
|
responseInstance := reflect.New(responseStruct).Interface()
|
||||||
// Получили структуру ответа
|
// Получили структуру ответа
|
||||||
@ -73,30 +89,42 @@ func handleOperation(method string, operation *openapi3.Operation) (reqParam, re
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Рекурсивное создание структуры из схемы с учетом $ref
|
// Рекурсивное создание структуры из схемы с учетом $ref
|
||||||
func buildDynamicStruct(schema *openapi3.SchemaRef) []reflect.StructField {
|
func buildDynamicStruct(doc *openapi.Document, schemaOrRef *openapi.SchemaOrReference) []reflect.StructField {
|
||||||
var sfields []reflect.StructField
|
var sfields []reflect.StructField
|
||||||
|
var schema *openapi.Schema
|
||||||
if len(schema.Value.Properties) == 0 {
|
if schemaOrRef.GetSchema() != nil {
|
||||||
return sfields
|
schema = schemaOrRef.GetSchema()
|
||||||
|
}
|
||||||
|
if schemaOrRef.GetReference() != nil {
|
||||||
|
name := strings.Split(schemaOrRef.GetReference().GetXRef(), "#/components/schemas/")[1]
|
||||||
|
fieldName := capitalize(name)
|
||||||
|
subBuilder := buildDynamicStruct(doc, findReference(doc, schemaOrRef.GetReference().GetXRef()))
|
||||||
|
sfield := reflect.StructField{
|
||||||
|
Name: fieldName,
|
||||||
|
Type: reflect.StructOf(subBuilder),
|
||||||
|
Tag: reflect.StructTag(fmt.Sprintf(`json:"%s"`, name)),
|
||||||
|
}
|
||||||
|
sfields = append(sfields, sfield)
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, prop := range schema.Value.Properties {
|
for _, prop := range schema.GetProperties().GetAdditionalProperties() {
|
||||||
fieldName := capitalize(name)
|
fieldName := capitalize(prop.GetName())
|
||||||
if prop.Ref != "" || prop.Value.Type.Is("object") {
|
if prop.GetValue().GetReference() != nil {
|
||||||
subBuilder := buildDynamicStruct(prop)
|
subBuilder := buildDynamicStruct(doc, prop.GetValue())
|
||||||
|
|
||||||
sfield := reflect.StructField{
|
sfield := reflect.StructField{
|
||||||
Name: fieldName,
|
Name: fieldName,
|
||||||
Type: reflect.StructOf(subBuilder),
|
Type: reflect.StructOf(subBuilder),
|
||||||
Tag: reflect.StructTag(fmt.Sprintf(`json:"%s"`, name)),
|
Tag: reflect.StructTag(fmt.Sprintf(`json:"%s"`, prop.GetName())),
|
||||||
}
|
}
|
||||||
|
|
||||||
sfields = append(sfields, sfield)
|
sfields = append(sfields, sfield)
|
||||||
} else {
|
}
|
||||||
|
if prop.GetValue().GetSchema() != nil {
|
||||||
sfield := reflect.StructField{
|
sfield := reflect.StructField{
|
||||||
Name: fieldName,
|
Name: fieldName,
|
||||||
Type: reflect.TypeOf(getGoType(prop)),
|
Type: reflect.TypeOf(getGoType(doc, prop.GetValue())),
|
||||||
Tag: reflect.StructTag(fmt.Sprintf(`json:"%s"`, name)),
|
Tag: reflect.StructTag(fmt.Sprintf(`json:"%s"`, prop.GetName())),
|
||||||
}
|
}
|
||||||
|
|
||||||
sfields = append(sfields, sfield)
|
sfields = append(sfields, sfield)
|
||||||
@ -106,25 +134,41 @@ func buildDynamicStruct(schema *openapi3.SchemaRef) []reflect.StructField {
|
|||||||
return sfields
|
return sfields
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func findReference(doc *openapi.Document, ref string) *openapi.SchemaOrReference {
|
||||||
|
var result *openapi.SchemaOrReference
|
||||||
|
ref = strings.Split(ref, "#/components/schemas/")[1]
|
||||||
|
|
||||||
|
for _, prop := range doc.Components.Schemas.GetAdditionalProperties() {
|
||||||
|
if prop.Name == ref {
|
||||||
|
result = prop.Value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// Преобразование типа OpenAPI в тип Go
|
// Преобразование типа OpenAPI в тип Go
|
||||||
func getGoType(schema *openapi3.SchemaRef) interface{} {
|
func getGoType(doc *openapi.Document, schema *openapi.SchemaOrReference) interface{} {
|
||||||
switch {
|
switch schema.GetSchema().Type {
|
||||||
case schema.Value.Type.Is("string"):
|
case "string":
|
||||||
return ""
|
return ""
|
||||||
case schema.Value.Type.Is("integer"):
|
case "integer":
|
||||||
return 0
|
return 0
|
||||||
case schema.Value.Type.Is("boolean"):
|
case "boolean":
|
||||||
return false
|
return false
|
||||||
case schema.Value.Type.Is("array"):
|
case "array":
|
||||||
return []interface{}{}
|
return []interface{}{}
|
||||||
case schema.Value.Type.Is("object"):
|
case "object":
|
||||||
return buildDynamicStruct(schema)
|
return buildDynamicStruct(doc, schema)
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func capitalize(fieldName string) string {
|
func capitalize(fieldName string) string {
|
||||||
|
if fieldName == "" {
|
||||||
|
return fieldName
|
||||||
|
}
|
||||||
// Заменяем точки на подчеркивания для унификации
|
// Заменяем точки на подчеркивания для унификации
|
||||||
fieldName = strings.ReplaceAll(fieldName, ".", "_")
|
fieldName = strings.ReplaceAll(fieldName, ".", "_")
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user