Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: generate schema for nested object in array #197

Merged
merged 1 commit into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 23 additions & 12 deletions pkg/tools/gen/genkcl_jsonschema.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"io"
"path/filepath"
"regexp"
"strconv"
"strings"

"github.com/iancoleman/strcase"
Expand All @@ -16,6 +17,7 @@ import (
type convertContext struct {
imports map[string]struct{}
resultMap map[string]convertResult
paths []string
}

type convertResult struct {
Expand All @@ -42,8 +44,9 @@ func (k *kclGenerator) genSchemaFromJsonSchema(w io.Writer, filename string, src
ctx := convertContext{
resultMap: make(map[string]convertResult),
imports: make(map[string]struct{}),
paths: []string{},
}
result := convertSchemaFromJsonSchema(ctx, js,
result := convertSchemaFromJsonSchema(&ctx, js,
strings.TrimSuffix(filepath.Base(filename), filepath.Ext(filename)))
if !result.IsSchema {
panic("result is not schema")
Expand All @@ -65,7 +68,7 @@ func (k *kclGenerator) genSchemaFromJsonSchema(w io.Writer, filename string, src
return k.genKcl(w, kclSch)
}

func convertSchemaFromJsonSchema(ctx convertContext, s *jsonschema.Schema, name string) convertResult {
func convertSchemaFromJsonSchema(ctx *convertContext, s *jsonschema.Schema, name string) convertResult {
// in jsonschema, type is one of True, False and Object
// we only convert Object type
if s.SchemaType != jsonschema.SchemaTypeObject {
Expand All @@ -84,6 +87,7 @@ func convertSchemaFromJsonSchema(ctx convertContext, s *jsonschema.Schema, name
name = "MyType"
}
result := convertResult{IsSchema: false, Name: name}
ctx.paths = append(ctx.paths, name)

isArray := false
typeList := typeUnion{}
Expand Down Expand Up @@ -113,10 +117,11 @@ func convertSchemaFromJsonSchema(ctx convertContext, s *jsonschema.Schema, name
logger.GetLogger().Warningf("unsupported multiple items: %#v", v)
break
}
for _, i := range v.Schemas {
item := convertSchemaFromJsonSchema(ctx, i, "items")
for i, val := range v.Schemas {
item := convertSchemaFromJsonSchema(ctx, val, "items"+strconv.Itoa(i))
if item.IsSchema {
typeList.Items = append(typeList.Items, typeCustom{Name: item.Name})
ctx.resultMap[item.schema.Name] = item
typeList.Items = append(typeList.Items, typeCustom{Name: item.schema.Name})
} else {
typeList.Items = append(typeList.Items, item.Type)
}
Expand All @@ -132,14 +137,12 @@ func convertSchemaFromJsonSchema(ctx convertContext, s *jsonschema.Schema, name
propSch := convertSchemaFromJsonSchema(ctx, val, key)
_, propSch.Required = required[key]
if propSch.IsSchema {
propSch.Name = strcase.ToCamel(key)
ctx.resultMap[propSch.Name] = propSch
ctx.resultMap[propSch.schema.Name] = propSch
}
propSch.Name = strcase.ToSnake(key)
result.Properties = append(result.Properties, propSch.property)
if !propSch.IsSchema {
for _, validate := range propSch.Validations {
validate.Name = propSch.Name
validate.Name = propSch.property.Name
result.Validations = append(result.Validations, validate)
}
}
Expand Down Expand Up @@ -174,6 +177,8 @@ func convertSchemaFromJsonSchema(ctx convertContext, s *jsonschema.Schema, name
typeName := strcase.ToCamel(v.Reference[strings.LastIndex(v.Reference, "/")+1:])
typeList.Items = []typeInterface{typeCustom{Name: typeName}}
case *jsonschema.Defs:
paths := ctx.paths
ctx.paths = []string{}
for key, val := range *v {
sch := convertSchemaFromJsonSchema(ctx, val, key)
if !sch.IsSchema {
Expand All @@ -192,6 +197,7 @@ func convertSchemaFromJsonSchema(ctx convertContext, s *jsonschema.Schema, name
}
ctx.resultMap[key] = sch
}
ctx.paths = paths
case *jsonschema.AdditionalProperties:
switch v.SchemaType {
case jsonschema.SchemaTypeObject:
Expand Down Expand Up @@ -270,7 +276,13 @@ func convertSchemaFromJsonSchema(ctx convertContext, s *jsonschema.Schema, name
}

if result.IsSchema {
result.Type = typeCustom{Name: strcase.ToCamel(name)}
var s strings.Builder
for _, p := range ctx.paths {
s.WriteString(strcase.ToCamel(p))
}
result.schema.Name = s.String()
result.schema.Description = result.Description
result.Type = typeCustom{Name: strcase.ToCamel(result.schema.Name)}
if len(result.Properties) == 0 && !result.HasIndexSignature {
result.HasIndexSignature = true
result.IndexSignature = indexSignature{Type: typePrimitive(typAny)}
Expand All @@ -286,10 +298,9 @@ func convertSchemaFromJsonSchema(ctx convertContext, s *jsonschema.Schema, name
result.Type = typePrimitive(typAny)
}
}
result.schema.Name = strcase.ToCamel(result.Name)
result.schema.Description = result.Description
result.property.Name = strcase.ToSnake(result.Name)
result.property.Description = result.Description
ctx.paths = ctx.paths[:len(ctx.paths)-1]
return result
}

Expand Down
8 changes: 4 additions & 4 deletions pkg/tools/gen/testdata/jsonschema/additional/expect.k
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ schema Ethernet:
Attributes
----------
name : str, optional
socket : Socket, optional, default is {"HTTP": 80, "HTTPS": 443}
socket : EthernetSocket, optional, default is {"HTTP": 80, "HTTPS": 443}
"""

name?: str
socket?: Socket = {"HTTP": 80, "HTTPS": 443}
socket?: EthernetSocket = {"HTTP": 80, "HTTPS": 443}

schema Socket:
schema EthernetSocket:
"""
Socket
EthernetSocket
"""

[...str]: int
Expand Down
86 changes: 86 additions & 0 deletions pkg/tools/gen/testdata/jsonschema/nested-items/expect.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
"""
This file was generated by the KCL auto-gen tool. DO NOT EDIT.
Editing this file might prove futile when you re-run the KCL auto-gen generate command.
"""

schema MonacoManifestSchema:
"""
MonacoManifestSchema

Attributes
----------
manifest_version : str, required
The schema version this manifest conforms to - e.g. 1.0
projects : [MonacoManifestSchemaProjectsItems0], required
The projects grouped by this manifest
environment_groups : [MonacoManifestSchemaEnvironmentGroupsItems0], required
The Environment groups to which projects in this manifest are deployed
"""

manifest_version: str
projects: [MonacoManifestSchemaProjectsItems0]
environment_groups: [MonacoManifestSchemaEnvironmentGroupsItems0]

schema MonacoManifestSchemaEnvironmentGroupsItems0:
"""
MonacoManifestSchemaEnvironmentGroupsItems0

Attributes
----------
name : str, optional
The name of this environment group
environments : [MonacoManifestSchemaEnvironmentGroupsItems0EnvironmentsItems0], optional
The environments in this group
"""

name?: str
environments?: [MonacoManifestSchemaEnvironmentGroupsItems0EnvironmentsItems0]

schema MonacoManifestSchemaEnvironmentGroupsItems0EnvironmentsItems0:
"""
MonacoManifestSchemaEnvironmentGroupsItems0EnvironmentsItems0

Attributes
----------
name : str, optional
The name of this environment
url : MonacoManifestSchemaEnvironmentGroupsItems0EnvironmentsItems0Url, optional
The URL of this environment
"""

name?: str
url?: MonacoManifestSchemaEnvironmentGroupsItems0EnvironmentsItems0Url

schema MonacoManifestSchemaEnvironmentGroupsItems0EnvironmentsItems0Url:
"""
The URL of this environment

Attributes
----------
type : str, optional
Optional Type of URL definition.
value : str, optional
The value of the URL, based on type either an URL or environment variable name
"""

type?: str
value?: str

schema MonacoManifestSchemaProjectsItems0:
"""
MonacoManifestSchemaProjectsItems0

Attributes
----------
name : str, required
The name of this project
type : str, optional
Optional Type of this project. Default: Simple
path : str, optional
Optional filepath of the project relative to the manifest.yaml location. Defaults to name
"""

name: str
type?: str
path?: str

81 changes: 81 additions & 0 deletions pkg/tools/gen/testdata/jsonschema/nested-items/input.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
{
"$id": "https://example.com/monaco.manifest.schema.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Dynatrace Monitoring as Code Manifest File",
"type": "object",
"properties": {
"manifestVersion": {
"type": "string",
"description": "The schema version this manifest conforms to - e.g. 1.0"
},
"projects": {
"type": "array",
"description": "The projects grouped by this manifest",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The name of this project"
},
"type": {
"type": "string",
"description": "Optional Type of this project. Default: Simple"
},
"path": {
"type": "string",
"description": "Optional filepath of the project relative to the manifest.yaml location. Defaults to name"
}
},
"required": [
"name"
]
}
},
"environmentGroups": {
"description": "The Environment groups to which projects in this manifest are deployed",
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The name of this environment group"
},
"environments": {
"description": "The environments in this group",
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The name of this environment"
},
"url": {
"description": "The URL of this environment",
"type": "object",
"properties": {
"type": {
"description": "Optional Type of URL definition.",
"type": "string"
},
"value": {
"type": "string",
"description": "The value of the URL, based on type either an URL or environment variable name"
}
}
}
}
}
}
}
}
}
},
"required": [
"manifestVersion",
"projects",
"environmentGroups"
]
}
8 changes: 4 additions & 4 deletions pkg/tools/gen/testdata/jsonschema/nested/expect.k
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ schema Book:
Attributes
----------
title : str, optional
author : Author, optional
author : BookAuthor, optional
"""

title?: str
author?: Author
author?: BookAuthor

schema Author:
schema BookAuthor:
"""
Author
BookAuthor

Attributes
----------
Expand Down
Loading