diff --git a/integration_test/integration_test.go b/integration_test/integration_test.go index dfb719b..1f5cdd6 100644 --- a/integration_test/integration_test.go +++ b/integration_test/integration_test.go @@ -93,6 +93,7 @@ func (s *MySuite) TestMessageComposer() { s.GenerateMessageTypesTest("testdata/ics721.json") s.GenerateMessageTypesTest("testdata/dao-dao-core.json") s.GenerateMessageTypesTest("testdata/axone-objectarium.json") + s.GenerateMessageTypesTest("testdata/map-test.json") } func (s *MySuite) TestQueryClient() { @@ -106,6 +107,7 @@ func (s *MySuite) TestQueryClient() { s.GenerateQueryClientTest("testdata/ics721.json") s.GenerateQueryClientTest("testdata/dao-dao-core.json") s.GenerateQueryClientTest("testdata/axone-objectarium.json") + s.GenerateQueryClientTest("testdata/map-test.json") } func (s *MySuite) TestInterchaintestScaffold() { diff --git a/integration_test/testdata/map-test.json b/integration_test/testdata/map-test.json new file mode 100644 index 0000000..a212581 --- /dev/null +++ b/integration_test/testdata/map-test.json @@ -0,0 +1,139 @@ +{ + "contract_name": "map-test", + "contract_version": "0.0.1", + "idl_version": "1.0.0", + "instantiate": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InstantiateMsg", + "description": "Instantiate message", + "type": "object", + "additionalProperties": false + }, + "execute": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ExecuteMsg", + "description": "Execute messages", + "oneOf": [ + { + "title": "Foo", + "type": "object", + "required": [ + "foo" + ], + "properties": { + "foo": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "query": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsg", + "description": "Query messages", + "oneOf": [ + { + "title": "MapString", + "type": "object", + "required": [ + "map_string" + ], + "properties": { + "map_string": { + "type": "object", + "required": [ + "foo" + ], + "properties": { + "foo": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "map_with_value" + ], + "properties": { + "map_with_value": { + "type": "object", + "required": [ + "foo" + ], + "properties": { + "foo": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/Value" + } + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ], + "definitions": { + "Value": { + "type": "object", + "required": [ + "value" + ], + "properties": { + "value": { + "type": "string" + } + }, + "additionalProperties": false + } + } + }, + "migrate": null, + "sudo": null, + "responses": { + "map_string": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "BarResponse", + "type": "object", + "required": [ + "foo" + ], + "properties": { + "foo": { + "description": "The foo value", + "type": "string" + } + }, + "additionalProperties": false + }, + "map_with_value": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "BarResponse", + "type": "object", + "required": [ + "foo" + ], + "properties": { + "foo": { + "description": "The foo value", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "description": "# map-test", + "title": "map-test" +} diff --git a/pkg/codegen/codegentests/cwics721_test.go b/pkg/codegen/codegentests/cwics721_test.go index 0e267fd..e4542e0 100644 --- a/pkg/codegen/codegentests/cwics721_test.go +++ b/pkg/codegen/codegentests/cwics721_test.go @@ -267,8 +267,10 @@ type QueryMsg_OutgoingChannels struct { } type ExecuteMsg_ReceiveNft Cw721ReceiveMsg -type ExecuteMsg_Pause struct{} -type ExecuteMsg_Callback CallbackMsg +type ( + ExecuteMsg_Pause struct{} + ExecuteMsg_Callback CallbackMsg +) type ExecuteMsg_AdminCleanAndBurnNft struct { ClassId string `json:"class_id"` diff --git a/pkg/codegen/properties.go b/pkg/codegen/properties.go index 3afa794..9860e14 100644 --- a/pkg/codegen/properties.go +++ b/pkg/codegen/properties.go @@ -194,6 +194,27 @@ func getType(name string, schema *schemas.JSONSchema, required *bool, typePrefix for k := range schema.Properties { typeStr = strcase.ToCamel(k) } + case schema.AdditionalProperties.JSONSchema != nil: + if len(schema.Properties) > 0 { + return "", fmt.Errorf("cannot determine the type of object %s: properties and additionalProperties are both defined", name) + } + if schema.AdditionalProperties.JSONSchema.Properties != nil { + return "", fmt.Errorf("cannot determine the type of object %s: a sub-object is defined in 'additionalProperties', which is currently not supported, please report this issue in https://github.com/srdtrk/go-codegen", name) + } + + itemType, err := getType(name, schema.AdditionalProperties.JSONSchema, nil, "", false) + if err != nil { + return "", err + } + + typeStr = "map[string]" + itemType + isOptional = false + case schema.AdditionalProperties.Bool != nil && *schema.AdditionalProperties.Bool: + if len(schema.Properties) > 0 { + return "", fmt.Errorf("cannot determine the type of object %s: properties and additionalProperties are both defined", name) + } + typeStr = "map[string]any" + isOptional = false default: return "", fmt.Errorf("cannot determine the type of object %s", name) } diff --git a/pkg/schemas/schema.go b/pkg/schemas/schema.go index 1aa45de..50da850 100644 --- a/pkg/schemas/schema.go +++ b/pkg/schemas/schema.go @@ -15,7 +15,7 @@ type JSONSchema struct { Required []string `json:"required,omitempty"` // Section 5.15. Properties map[string]*JSONSchema `json:"properties,omitempty"` // Section 5.16. PatternProperties map[string]*JSONSchema `json:"patternProperties,omitempty"` // Section 5.17. - AdditionalProperties *bool `json:"additionalProperties,omitempty"` // Section 5.18. + AdditionalProperties *JSONSchemaOrBool `json:"additionalProperties,omitempty"` // Section 5.18. Type TypeList `json:"type,omitempty"` // Section 5.21. AllOf []*JSONSchema `json:"allOf,omitempty"` // Section 5.22. AnyOf []*JSONSchema `json:"anyOf,omitempty"` // Section 5.23. @@ -83,3 +83,17 @@ func (t *TypeList) UnmarshalJSON(b []byte) error { return nil } + +// JSONSchemaOrBool represents a JSONSchema or a boolean value. +type JSONSchemaOrBool struct { + JSONSchema *JSONSchema + Bool *bool +} + +func (t *JSONSchemaOrBool) UnmarshalJSON(b []byte) error { + if err := json.Unmarshal(b, &t.Bool); err == nil { + return nil + } + t.Bool = nil + return json.Unmarshal(b, &t.JSONSchema) +}