mirror of https://github.com/databricks/cli.git
added slice of object handling
This commit is contained in:
parent
babd7fa4eb
commit
010f60d498
|
@ -26,6 +26,7 @@ type Property struct {
|
||||||
|
|
||||||
type Item struct {
|
type Item struct {
|
||||||
Type JsType `json:"type"`
|
Type JsType `json:"type"`
|
||||||
|
Properities map[string]*Property `json:"properties,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSchema(golangType reflect.Type) (*Schema, error) {
|
func NewSchema(golangType reflect.Type) (*Schema, error) {
|
||||||
|
@ -79,6 +80,7 @@ func javascriptType(golangType reflect.Type) (JsType, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: add a simple test for this
|
||||||
func errWithTrace(prefix string, trace []reflect.Type) error {
|
func errWithTrace(prefix string, trace []reflect.Type) error {
|
||||||
traceString := ""
|
traceString := ""
|
||||||
for _, golangType := range trace {
|
for _, golangType := range trace {
|
||||||
|
@ -88,6 +90,9 @@ func errWithTrace(prefix string, trace []reflect.Type) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: handle case of self referential pointers in structs
|
// TODO: handle case of self referential pointers in structs
|
||||||
|
// TODO: add handling of embedded types
|
||||||
|
|
||||||
|
// TODO: add tests for the error cases, forcefully triggering them
|
||||||
|
|
||||||
// TODO: add doc string explaining numHistoryOccurances
|
// TODO: add doc string explaining numHistoryOccurances
|
||||||
func toProperity(golangType reflect.Type, traceSet map[reflect.Type]struct{}, traceSlice []reflect.Type) (*Property, error) {
|
func toProperity(golangType reflect.Type, traceSet map[reflect.Type]struct{}, traceSlice []reflect.Type) (*Property, error) {
|
||||||
|
@ -100,28 +105,45 @@ func toProperity(golangType reflect.Type, traceSet map[reflect.Type]struct{}, tr
|
||||||
|
|
||||||
rootJavascriptType, err := javascriptType(golangType)
|
rootJavascriptType, err := javascriptType(golangType)
|
||||||
|
|
||||||
// TODO: recursive debugging can be a pain. Make sure the error localtion
|
|
||||||
// floats up
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errWithTrace(err.Error(), traceSlice)
|
||||||
}
|
}
|
||||||
|
|
||||||
var items *Item
|
var items *Item
|
||||||
if golangType.Kind() == reflect.Array || golangType.Kind() == reflect.Slice {
|
if golangType.Kind() == reflect.Array || golangType.Kind() == reflect.Slice {
|
||||||
elemJsType, err := javascriptType(golangType.Elem())
|
elemGolangType := golangType.Elem()
|
||||||
|
elemJavascriptType, err := javascriptType(elemGolangType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO: float up error in case of deep recursion
|
return nil, errWithTrace(err.Error(), traceSlice)
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// detect cycles. Fail if a cycle is detected
|
||||||
|
// TODO: Add references here for cycles
|
||||||
|
_, ok := traceSet[elemGolangType]
|
||||||
|
if ok {
|
||||||
|
fmt.Println("[DEBUG] traceSet: ", traceSet)
|
||||||
|
return nil, errWithTrace("cycle detected", traceSlice)
|
||||||
|
}
|
||||||
|
// add current child field to history
|
||||||
|
traceSet[elemGolangType] = struct{}{}
|
||||||
|
elemProps, err := toProperity(elemGolangType, traceSet, traceSlice)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errWithTrace(err.Error(), traceSlice)
|
||||||
|
}
|
||||||
|
|
||||||
items = &Item{
|
items = &Item{
|
||||||
// TODO: what if there is an array of objects?
|
// TODO: Add a test for slice of object
|
||||||
Type: elemJsType,
|
Type: elemJavascriptType,
|
||||||
|
Properities: elemProps.Properities,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// var additionalProperties *Property
|
||||||
|
// if golangType.Kind() == reflect.Map {
|
||||||
|
// additionalProperties =
|
||||||
|
// }
|
||||||
|
|
||||||
properities := map[string]*Property{}
|
properities := map[string]*Property{}
|
||||||
|
|
||||||
// TODO: for reflect.Map case for prop computation
|
|
||||||
if golangType.Kind() == reflect.Struct {
|
if golangType.Kind() == reflect.Struct {
|
||||||
for i := 0; i < golangType.NumField(); i++ {
|
for i := 0; i < golangType.NumField(); i++ {
|
||||||
child := golangType.Field(i)
|
child := golangType.Field(i)
|
||||||
|
@ -149,9 +171,8 @@ func toProperity(golangType reflect.Type, traceSet map[reflect.Type]struct{}, tr
|
||||||
// recursively compute properties for this child field
|
// recursively compute properties for this child field
|
||||||
fieldProps, err := toProperity(child.Type, traceSet, traceSlice)
|
fieldProps, err := toProperity(child.Type, traceSet, traceSlice)
|
||||||
|
|
||||||
// TODO: make sure this error floats up with context
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errWithTrace(err.Error(), traceSlice)
|
||||||
}
|
}
|
||||||
|
|
||||||
// traversal complete, delete child from history
|
// traversal complete, delete child from history
|
||||||
|
|
|
@ -160,3 +160,80 @@ func TestObjectSchema(t *testing.T) {
|
||||||
fmt.Println("[DEBUG] expected: ", expected)
|
fmt.Println("[DEBUG] expected: ", expected)
|
||||||
assert.Equal(t, expected, string(jsonSchema))
|
assert.Equal(t, expected, string(jsonSchema))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSliceOfObjectsSchema(t *testing.T) {
|
||||||
|
type Person struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Age int `json:"age,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Plot struct {
|
||||||
|
MainCharacters []Person `json:"main_characters"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Story struct {
|
||||||
|
Hero Person `json:"hero"`
|
||||||
|
Villian Person `json:"villian"`
|
||||||
|
Plot Plot `json:"plot"`
|
||||||
|
}
|
||||||
|
|
||||||
|
elem := Story{}
|
||||||
|
|
||||||
|
schema, err := NewSchema(reflect.TypeOf(elem))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
jsonSchema, err := json.MarshalIndent(schema, " ", " ")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
expected :=
|
||||||
|
`{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"hero": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"age": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"plot": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"main_characters": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"age": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"villian": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"age": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
|
||||||
|
fmt.Println("[DEBUG] actual: ", string(jsonSchema))
|
||||||
|
fmt.Println("[DEBUG] expected: ", expected)
|
||||||
|
assert.Equal(t, expected, string(jsonSchema))
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue