From 469d1582a58e27010d7d52ede3f9296a7624adf8 Mon Sep 17 00:00:00 2001 From: Joel Hendrix Date: Thu, 11 Jun 2020 15:27:13 -0700 Subject: [PATCH] Add support for additional properties (#423) Add an 'AdditionalProperties' map on applicable types along with a custom marshaller and unmarshaller. If a type supports additional properties and also has a field named 'AdditionalProperties' rename the field by appending a '1'. Note that the current implementation doesn't work for discriminated types that contain additional properties, or types that use XML. Will be fixed in later PRs. --- rushScripts/regeneration.js | 2 +- src/common/helpers.ts | 13 +- src/generator/models.ts | 117 ++++- src/transform/namer.ts | 9 +- src/transform/transform.ts | 15 +- .../additionalpropsgroup_test.go | 222 +++++++++ .../additionalpropertiesgroup/models.go | 126 ----- .../additionalpropertiesgroup/pets.go | 141 ------ .../additionalpropertiesgroup/models.go | 40 -- .../additionalpropertiesgroup/pets.go | 136 ------ .../client.go | 7 +- .../generated/additionalpropsgroup/models.go | 430 ++++++++++++++++++ .../generated/additionalpropsgroup/pets.go | 309 +++++++++++++ .../autorest/generated/complexgroup/models.go | 4 +- test/storage/2019-07-07/azblob/models.go | 4 +- 15 files changed, 1119 insertions(+), 456 deletions(-) create mode 100644 test/autorest/additionalpropsgroup/additionalpropsgroup_test.go delete mode 100644 test/autorest/generated/additionalpropertiesgroup/internal/additionalpropertiesgroup/models.go delete mode 100644 test/autorest/generated/additionalpropertiesgroup/internal/additionalpropertiesgroup/pets.go delete mode 100644 test/autorest/generated/additionalpropertiesgroup/models.go delete mode 100644 test/autorest/generated/additionalpropertiesgroup/pets.go rename test/autorest/generated/{additionalpropertiesgroup => additionalpropsgroup}/client.go (91%) create mode 100644 test/autorest/generated/additionalpropsgroup/models.go create mode 100644 test/autorest/generated/additionalpropsgroup/pets.go diff --git a/rushScripts/regeneration.js b/rushScripts/regeneration.js index 9bea947ca..3f3738489 100644 --- a/rushScripts/regeneration.js +++ b/rushScripts/regeneration.js @@ -5,7 +5,7 @@ const exec = require('child_process').exec; const swaggerDir = 'src/node_modules/@microsoft.azure/autorest.testserver/swagger/'; const goMappings = { - //'additionalpropertiesgroup': 'additionalProperties.json', + 'additionalpropsgroup': 'additionalProperties.json', 'arraygroup': 'body-array.json', 'azurereportgroup': 'azure-report.json', 'azurespecialsgroup': 'azure-special-properties.json', diff --git a/src/common/helpers.ts b/src/common/helpers.ts index 0f058243a..811abb915 100644 --- a/src/common/helpers.ts +++ b/src/common/helpers.ts @@ -3,7 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ArraySchema, ObjectSchema, Operation, Parameter, Response, Schema, SchemaResponse } from '@azure-tools/codemodel'; +import { ArraySchema, ObjectSchema, Operation, Parameter, Response, Schema, SchemaResponse, SchemaType } from '@azure-tools/codemodel'; +import { values } from '@azure-tools/linq'; // aggregates the Parameter in op.parameters and the first request export function aggregateParameters(op: Operation): Array { @@ -55,3 +56,13 @@ export function isLROOperation(op: Operation): boolean { export function isObjectSchema(obj: Schema): obj is ObjectSchema { return (obj as ObjectSchema).properties !== undefined; } + +// returns the additional properties schema if the ObjectSchema defines 'additionalProperties' +export function hasAdditionalProperties(obj: ObjectSchema): Schema | undefined { + for (const parent of values(obj.parents?.immediate)) { + if (parent.type === SchemaType.Dictionary) { + return parent; + } + } + return undefined; +} diff --git a/src/generator/models.ts b/src/generator/models.ts index d2161095a..e2553e4df 100644 --- a/src/generator/models.ts +++ b/src/generator/models.ts @@ -4,10 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import { Session } from '@azure-tools/autorest-extension-base'; -import { camelCase, comment, pascalCase } from '@azure-tools/codegen'; -import { CodeModel, ConstantSchema, GroupProperty, ImplementationLocation, ObjectSchema, Language, Schema, SchemaType, Parameter, Property } from '@azure-tools/codemodel'; +import { comment, pascalCase } from '@azure-tools/codegen'; +import { CodeModel, ConstantSchema, GroupProperty, ImplementationLocation, ObjectSchema, Language, Schema, SchemaType, Parameter, Property, DictionarySchema } from '@azure-tools/codemodel'; import { values } from '@azure-tools/linq'; -import { isArraySchema, isObjectSchema } from '../common/helpers'; +import { isArraySchema, isObjectSchema, hasAdditionalProperties } from '../common/helpers'; import { contentPreamble, hasDescription, sortAscending, substituteDiscriminator } from './helpers'; import { ImportManager } from './imports'; @@ -152,7 +152,8 @@ class StructDef { let tag = ` \`${this.Language.marshallingFormat}:"${serialization}"\``; // if this is a response type then omit the tag IFF the marshalling format is // JSON, it's a header or is the RawResponse field. XML marshalling needs a tag. - if (this.Language.responseType === true && (this.Language.marshallingFormat !== 'xml' || prop.language.go!.name === 'RawResponse')) { + // also omit the tag for additionalProperties + if ((this.Language.responseType === true && (this.Language.marshallingFormat !== 'xml' || prop.language.go!.name === 'RawResponse')) || prop.language.go!.isAdditionalProperties) { tag = ''; } let pointer = '*'; @@ -238,6 +239,7 @@ function generateStructs(objects?: ObjectSchema[]): StructDef[] { text += '}\n\n'; structDef.Methods.push({ name: 'Error', text: text }); } + // TODO: unify marshalling schemes if (obj.discriminator) { // only need to generate interface method and internal marshaller for discriminators (Fish, Salmon, Shark) generateDiscriminatorMethods(obj, structDef, parentType!); @@ -252,11 +254,19 @@ function generateStructs(objects?: ObjectSchema[]): StructDef[] { } else if (hasPolymorphicField) { generateDiscriminatedTypeUnmarshaller(obj, structDef, parentType!); } else if (obj.language.go!.needsDateTimeMarshalling || obj.language.go!.xmlWrapperName) { - // TODO: unify marshalling schemes? generateMarshaller(structDef); if (obj.language.go!.needsDateTimeMarshalling) { generateUnmarshaller(structDef); } + } else if (obj.language.go!.marshallingFormat === 'json' && (hasAdditionalProperties(obj) || (parentType && hasAdditionalProperties(parentType)))) { + // TODO: support for XML + generateAdditionalPropertiesMarshaller(structDef, parentType); + let schema = hasAdditionalProperties(obj); + if (!schema) { + // must be the parent + schema = hasAdditionalProperties(parentType!); + } + generateAdditionalPropertiesUnmarshaller(structDef, (schema).elementType, parentType); } structDef.ComposedOf.sort((a: ObjectSchema, b: ObjectSchema) => { return sortAscending(a.language.go!.name, b.language.go!.name); }); structTypes.push(structDef); @@ -382,6 +392,9 @@ function generateDiscriminatedTypeMarshaller(obj: ObjectSchema, structDef: Struc let marshaller = `func (${receiver} ${typeName}) MarshalJSON() ([]byte, error) {\n`; marshaller += `\tobjectMap := ${receiver}.${parentType!.language.go!.name}.marshalInternal(${obj.discriminatorValue})\n`; for (const prop of values(structDef.Properties)) { + if (prop.language.go!.isAdditionalProperties) { + continue; + } marshaller += `\tif ${receiver}.${prop.language.go!.name} != nil {\n`; if (prop.schema.language.go!.internalTimeType) { marshaller += `\t\tobjectMap["${prop.serializedName}"] = (*${prop.schema.language.go!.internalTimeType})(${receiver}.${prop.language.go!.name})\n`; @@ -415,6 +428,9 @@ function generateDiscriminatedTypeUnmarshaller(obj: ObjectSchema, structDef: Str unmarshaller += '\t\tswitch k {\n'; // unmarshal each field one by one for (const prop of values(structDef.Properties)) { + if (prop.language.go!.isAdditionalProperties) { + continue; + } unmarshaller += `\t\tcase "${prop.serializedName}":\n`; unmarshaller += '\t\t\tif v != nil {\n'; if (prop.schema.language.go!.discriminatorInterface) { @@ -532,3 +548,94 @@ function generateAliasType(structDef: StructDef, receiver: string, forMarshal: b text += `\t}\n`; return text; } + +function generateAdditionalPropertiesMarshaller(structDef: StructDef, parentType?: ObjectSchema) { + imports.add('encoding/json'); + const typeName = structDef.Language.name; + const receiver = typeName[0].toLowerCase(); + // generate marshaller method + let marshaller = `func (${receiver} ${typeName}) MarshalJSON() ([]byte, error) {\n`; + marshaller += '\tobjectMap := make(map[string]interface{})\n'; + const emitMarshaller = function (prop: Property): string { + let text = `\tif ${receiver}.${prop.language.go!.name} != nil {\n`; + if (prop.schema.language.go!.internalTimeType) { + text += `\t\tobjectMap["${prop.serializedName}"] = (*${prop.schema.language.go!.internalTimeType})(${receiver}.${prop.language.go!.name})\n`; + } else { + text += `\t\tobjectMap["${prop.serializedName}"] = ${receiver}.${prop.language.go!.name}\n`; + } + text += `\t}\n`; + return text; + } + // TODO: multiple inheritance + for (const prop of values(parentType?.properties)) { + if (prop.language.go!.isAdditionalProperties) { + continue; + } + marshaller += emitMarshaller(prop); + } + for (const prop of values(structDef.Properties)) { + if (prop.language.go!.isAdditionalProperties) { + continue; + } + marshaller += emitMarshaller(prop); + } + marshaller += `\tif ${receiver}.AdditionalProperties != nil {\n`; + marshaller += `\t\tfor k, v := range *${receiver}.AdditionalProperties {\n`; + marshaller += '\t\t\tobjectMap[k] = v\n'; + marshaller += '\t\t}\n';; + marshaller += '\t}\n'; + marshaller += '\treturn json.Marshal(objectMap)\n'; + marshaller += '}\n\n'; + structDef.Methods.push({ name: 'MarshalJSON', text: marshaller }); +} + +function generateAdditionalPropertiesUnmarshaller(structDef: StructDef, elementType: Schema, parentType?: ObjectSchema) { + imports.add('encoding/json'); + const typeName = structDef.Language.name; + const receiver = typeName[0].toLowerCase(); + let unmarshaller = `func (${receiver} *${typeName}) UnmarshalJSON(data []byte) error {\n`; + unmarshaller += '\tvar rawMsg map[string]*json.RawMessage\n'; + unmarshaller += '\tif err := json.Unmarshal(data, &rawMsg); err != nil {\n'; + unmarshaller += '\t\treturn err\n'; + unmarshaller += '\t}\n'; + unmarshaller += '\tfor k, v := range rawMsg {\n'; + unmarshaller += '\t\tvar err error\n'; + unmarshaller += '\t\tswitch k {\n'; + const emitUnmarshaller = function (prop: Property): string { + let text = `\t\tcase "${prop.serializedName}":\n`; + text += '\t\t\tif v != nil {\n'; + text += `\t\t\t\terr = json.Unmarshal(*v, &${receiver}.${prop.language.go!.name})\n`; + text += '\t\t\t}\n'; + return text; + } + // TODO: multiple inheritance + for (const prop of values(parentType?.properties)) { + if (prop.language.go!.isAdditionalProperties) { + continue; + } + unmarshaller += emitUnmarshaller(prop); + } + for (const prop of values(structDef.Properties)) { + if (prop.language.go!.isAdditionalProperties) { + continue; + } + unmarshaller += emitUnmarshaller(prop); + } + unmarshaller += '\t\tdefault:\n'; + unmarshaller += `\t\t\tif ${receiver}.AdditionalProperties == nil {\n`; + unmarshaller += `\t\t\t\t${receiver}.AdditionalProperties = &map[string]${elementType.language.go!.name}{}\n`; + unmarshaller += '\t\t\t}\n'; + unmarshaller += '\t\t\tif v != nil {\n'; + unmarshaller += `\t\t\t\tvar aux ${elementType.language.go!.name}\n`; + unmarshaller += '\t\t\t\terr = json.Unmarshal(*v, &aux)\n'; + unmarshaller += `\t\t\t\t(*${receiver}.AdditionalProperties)[k] = aux\n`; + unmarshaller += '\t\t\t}\n'; + unmarshaller += '\t\t}\n'; + unmarshaller += '\t\tif err != nil {\n'; + unmarshaller += '\t\t\treturn err\n'; + unmarshaller += '\t\t}\n'; + unmarshaller += '\t}\n'; + unmarshaller += '\treturn nil\n'; + unmarshaller += '}\n\n'; + structDef.Methods.push({ name: 'UnmarshalJSON', text: unmarshaller }); +} diff --git a/src/transform/namer.ts b/src/transform/namer.ts index 270fb38eb..083086d6b 100644 --- a/src/transform/namer.ts +++ b/src/transform/namer.ts @@ -6,9 +6,9 @@ import { pascalCase, camelCase } from '@azure-tools/codegen'; import { Session } from '@azure-tools/autorest-extension-base'; import { CodeModel, Language } from '@azure-tools/codemodel'; -import { length, visitor, clone, values } from '@azure-tools/linq'; +import { visitor, clone, values } from '@azure-tools/linq'; import { CommonAcronyms, ReservedWords } from './mappings'; -import { aggregateParameters, isLROOperation } from '../common/helpers'; +import { aggregateParameters, hasAdditionalProperties, isLROOperation } from '../common/helpers'; const requestMethodSuffix = 'CreateRequest'; const responseMethodSuffix = 'HandleResponse'; @@ -62,6 +62,11 @@ export async function namer(session: Session) { for (const prop of values(obj.properties)) { const details = prop.language.go; details.name = getEscapedReservedName(removePrefix(capitalizeAcronyms(pascalCase(details.name)), 'XMS'), 'Field'); + if (hasAdditionalProperties(obj) && details.name === 'AdditionalProperties') { + // this is the case where a type contains the generic additional properties + // and also has a field named additionalProperties. we rename the field. + details.name = 'AdditionalProperties1'; + } } } diff --git a/src/transform/transform.ts b/src/transform/transform.ts index bbf0f9994..1a8b656d6 100644 --- a/src/transform/transform.ts +++ b/src/transform/transform.ts @@ -7,7 +7,7 @@ import { camelCase, KnownMediaType, pascalCase, serialize } from '@azure-tools/c import { Host, startSession, Session } from '@azure-tools/autorest-extension-base'; import { ObjectSchema, ArraySchema, ChoiceValue, codeModelSchema, CodeModel, DateTimeSchema, GroupProperty, HttpHeader, HttpResponse, ImplementationLocation, Language, OperationGroup, SchemaType, NumberSchema, Operation, SchemaResponse, Parameter, Property, Protocols, Response, Schema, DictionarySchema, Protocol, ChoiceSchema, SealedChoiceSchema, ConstantSchema } from '@azure-tools/codemodel'; import { items, values } from '@azure-tools/linq'; -import { aggregateParameters, isPageableOperation, isObjectSchema, isSchemaResponse, PagerInfo, isLROOperation, PollerInfo } from '../common/helpers'; +import { aggregateParameters, hasAdditionalProperties, isPageableOperation, isObjectSchema, isSchemaResponse, PagerInfo, isLROOperation, PollerInfo } from '../common/helpers'; import { namer, removePrefix } from './namer'; // The transformer adds Go-specific information to the code model. @@ -35,6 +35,12 @@ export async function transform(host: Host) { async function process(session: Session) { processOperationRequests(session); processOperationResponses(session); + // fix up dictionary element types (additional properties) + // this must happen before processing objects as we depend on the + // schema type being an actual Go type. + for (const dictionary of values(session.model.schemas.dictionaries)) { + dictionary.elementType.language.go!.name = schemaTypeToGoType(session.model, dictionary.elementType, false); + } // fix up struct field types for (const obj of values(session.model.schemas.objects)) { if (obj.discriminator) { @@ -73,6 +79,13 @@ async function process(session: Session) { // the format to JSON as the vast majority of specs use JSON. obj.language.go!.marshallingFormat = 'json'; } + const addPropsSchema = hasAdditionalProperties(obj); + if (addPropsSchema) { + // add an 'AdditionalProperties' field to the type + const addProps = newProperty('AdditionalProperties', 'Contains additional key/value pairs not defined in the schema.', addPropsSchema); + addProps.language.go!.isAdditionalProperties = true; + obj.properties?.push(addProps); + } } // fix up enum types for (const choice of values(session.model.schemas.choices)) { diff --git a/test/autorest/additionalpropsgroup/additionalpropsgroup_test.go b/test/autorest/additionalpropsgroup/additionalpropsgroup_test.go new file mode 100644 index 000000000..b6fa33f04 --- /dev/null +++ b/test/autorest/additionalpropsgroup/additionalpropsgroup_test.go @@ -0,0 +1,222 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +package additionalpropsgrouptest + +import ( + "context" + "encoding/base64" + "generatortests/autorest/generated/additionalpropsgroup" + "generatortests/helpers" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/to" +) + +func getPetsOperations(t *testing.T) additionalpropsgroup.PetsOperations { + client, err := additionalpropsgroup.NewDefaultClient(nil) + if err != nil { + t.Fatalf("failed to create client: %v", err) + } + return client.PetsOperations() +} + +// CreateApInProperties - Create a Pet which contains more properties than what is defined. +func TestCreateApInProperties(t *testing.T) { + client := getPetsOperations(t) + result, err := client.CreateApInProperties(context.Background(), additionalpropsgroup.PetApInProperties{ + ID: to.Int32Ptr(4), + Name: to.StringPtr("Bunny"), + AdditionalProperties: &map[string]float32{ + "height": 5.61, + "weight": 599, + "footsize": 11.5, + }, + }) + if err != nil { + t.Fatal(err) + } + helpers.DeepEqualOrFatal(t, result.PetApInProperties, &additionalpropsgroup.PetApInProperties{ + ID: to.Int32Ptr(4), + Name: to.StringPtr("Bunny"), + Status: to.BoolPtr(true), + AdditionalProperties: &map[string]float32{ + "height": 5.61, + "weight": 599, + "footsize": 11.5, + }, + }) +} + +// CreateApInPropertiesWithApstring - Create a Pet which contains more properties than what is defined. +func TestCreateApInPropertiesWithApstring(t *testing.T) { + client := getPetsOperations(t) + result, err := client.CreateApInPropertiesWithApstring(context.Background(), additionalpropsgroup.PetApInPropertiesWithApstring{ + ID: to.Int32Ptr(5), + Name: to.StringPtr("Funny"), + OdataLocation: to.StringPtr("westus"), + AdditionalProperties: &map[string]string{ + "color": "red", + "city": "Seattle", + "food": "tikka masala", + }, + AdditionalProperties1: &map[string]float32{ + "height": 5.61, + "weight": 599, + "footsize": 11.5, + }, + }) + if err != nil { + t.Fatal(err) + } + helpers.DeepEqualOrFatal(t, result.PetApInPropertiesWithApstring, &additionalpropsgroup.PetApInPropertiesWithApstring{ + ID: to.Int32Ptr(5), + Name: to.StringPtr("Funny"), + OdataLocation: to.StringPtr("westus"), + Status: to.BoolPtr(true), + AdditionalProperties: &map[string]string{ + "color": "red", + "city": "Seattle", + "food": "tikka masala", + }, + AdditionalProperties1: &map[string]float32{ + "height": 5.61, + "weight": 599, + "footsize": 11.5, + }, + }) +} + +// CreateApObject - Create a Pet which contains more properties than what is defined. +func TestCreateApObject(t *testing.T) { + client := getPetsOperations(t) + result, err := client.CreateApObject(context.Background(), additionalpropsgroup.PetApObject{ + ID: to.Int32Ptr(2), + Name: to.StringPtr("Hira"), + AdditionalProperties: &map[string]interface{}{ + "siblings": []interface{}{ + map[string]interface{}{ + "id": float64(1), + "name": "Puppy", + "birthdate": "2017-12-13T02:29:51Z", + "complexProperty": map[string]interface{}{ + "color": "Red", + }, + }, + }, + "picture": base64.StdEncoding.EncodeToString([]byte{255, 255, 255, 255, 254}), + }, + }) + if err != nil { + t.Fatal(err) + } + helpers.DeepEqualOrFatal(t, result.PetApObject, &additionalpropsgroup.PetApObject{ + ID: to.Int32Ptr(2), + Name: to.StringPtr("Hira"), + Status: to.BoolPtr(true), + AdditionalProperties: &map[string]interface{}{ + "siblings": []interface{}{ + map[string]interface{}{ + "id": float64(1), + "name": "Puppy", + "birthdate": "2017-12-13T02:29:51Z", + "complexProperty": map[string]interface{}{ + "color": "Red", + }, + }, + }, + "picture": base64.StdEncoding.EncodeToString([]byte{255, 255, 255, 255, 254}), + }, + }) +} + +// CreateApString - Create a Pet which contains more properties than what is defined. +func TestCreateApString(t *testing.T) { + client := getPetsOperations(t) + result, err := client.CreateApString(context.Background(), additionalpropsgroup.PetApString{ + ID: to.Int32Ptr(3), + Name: to.StringPtr("Tommy"), + AdditionalProperties: &map[string]string{ + "color": "red", + "weight": "10 kg", + "city": "Bombay", + }, + }) + if err != nil { + t.Fatal(err) + } + helpers.DeepEqualOrFatal(t, result.PetApString, &additionalpropsgroup.PetApString{ + ID: to.Int32Ptr(3), + Name: to.StringPtr("Tommy"), + Status: to.BoolPtr(true), + AdditionalProperties: &map[string]string{ + "color": "red", + "weight": "10 kg", + "city": "Bombay", + }, + }) +} + +// CreateApTrue - Create a Pet which contains more properties than what is defined. +func TestCreateApTrue(t *testing.T) { + client := getPetsOperations(t) + result, err := client.CreateApTrue(context.Background(), additionalpropsgroup.PetApTrue{ + ID: to.Int32Ptr(1), + Name: to.StringPtr("Puppy"), + AdditionalProperties: &map[string]interface{}{ + "birthdate": "2017-12-13T02:29:51Z", + "complexProperty": map[string]interface{}{ + "color": "Red", + }, + }, + }) + if err != nil { + t.Fatal(err) + } + helpers.DeepEqualOrFatal(t, result.PetApTrue, &additionalpropsgroup.PetApTrue{ + ID: to.Int32Ptr(1), + Name: to.StringPtr("Puppy"), + Status: to.BoolPtr(true), + AdditionalProperties: &map[string]interface{}{ + "birthdate": "2017-12-13T02:29:51Z", + "complexProperty": map[string]interface{}{ + "color": "Red", + }, + }, + }) +} + +// CreateCatApTrue - Create a CatAPTrue which contains more properties than what is defined. +func TestCreateCatApTrue(t *testing.T) { + client := getPetsOperations(t) + result, err := client.CreateCatApTrue(context.Background(), additionalpropsgroup.CatApTrue{ + PetApTrue: additionalpropsgroup.PetApTrue{ + ID: to.Int32Ptr(1), + Name: to.StringPtr("Lisa"), + AdditionalProperties: &map[string]interface{}{ + "birthdate": "2017-12-13T02:29:51Z", + "complexProperty": map[string]interface{}{ + "color": "Red", + }, + }, + }, + Friendly: to.BoolPtr(true), + }) + if err != nil { + t.Fatal(err) + } + helpers.DeepEqualOrFatal(t, result.CatApTrue, &additionalpropsgroup.CatApTrue{ + PetApTrue: additionalpropsgroup.PetApTrue{ + ID: to.Int32Ptr(1), + Name: to.StringPtr("Lisa"), + Status: to.BoolPtr(true), + AdditionalProperties: &map[string]interface{}{ + "birthdate": "2017-12-13T02:29:51Z", + "complexProperty": map[string]interface{}{ + "color": "Red", + }, + }, + }, + Friendly: to.BoolPtr(true), + }) +} diff --git a/test/autorest/generated/additionalpropertiesgroup/internal/additionalpropertiesgroup/models.go b/test/autorest/generated/additionalpropertiesgroup/internal/additionalpropertiesgroup/models.go deleted file mode 100644 index 8f63ec92d..000000000 --- a/test/autorest/generated/additionalpropertiesgroup/internal/additionalpropertiesgroup/models.go +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. -// Code generated by Microsoft (R) AutoRest Code Generator. -// Changes may cause incorrect behavior and will be lost if the code is regenerated. - -package additionalpropertiesgroup - -import ( - "fmt" - "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "net/http" -) - -type CatApTrue struct { - Friendly *bool `json:"friendly,omitempty"` -} - -type Error struct { - Message *string `json:"message,omitempty"` - Status *int32 `json:"status,omitempty"` -} - -func newError(resp *azcore.Response) error { - err := Error{} - if err := resp.UnmarshalAsJSON(&err); err != nil { - return err - } - return err -} - -func (e Error) Error() string { - msg := "" - if e.Message != nil { - msg += fmt.Sprintf("Message: %v\n", *e.Message) - } - if e.Status != nil { - msg += fmt.Sprintf("Status: %v\n", *e.Status) - } - if msg == "" { - msg = "missing error info" - } - return msg -} - -type PetApInProperties struct { - // Dictionary of - AdditionalProperties *map[string]*float32 `json:"additionalProperties,omitempty"` - ID *int32 `json:"id,omitempty"` - Name *string `json:"name,omitempty"` - Status *bool `json:"status,omitempty"` -} - -type PetApInPropertiesWithApstring struct { - // Dictionary of - AdditionalProperties *map[string]*float32 `json:"additionalProperties,omitempty"` - ID *int32 `json:"id,omitempty"` - Name *string `json:"name,omitempty"` - OdataLocation *string `json:"@odata.location,omitempty"` - Status *bool `json:"status,omitempty"` -} - -type PetApObject struct { - ID *int32 `json:"id,omitempty"` - Name *string `json:"name,omitempty"` - Status *bool `json:"status,omitempty"` -} - -type PetApString struct { - ID *int32 `json:"id,omitempty"` - Name *string `json:"name,omitempty"` - Status *bool `json:"status,omitempty"` -} - -type PetApTrue struct { - ID *int32 `json:"id,omitempty"` - Name *string `json:"name,omitempty"` - Status *bool `json:"status,omitempty"` -} - -// PetsCreateApInPropertiesResponse contains the response from method Pets.CreateApInProperties. -type PetsCreateApInPropertiesResponse struct { - PetApInProperties *PetApInProperties - - // RawResponse contains the underlying HTTP response. - RawResponse *http.Response -} - -// PetsCreateApInPropertiesWithApstringResponse contains the response from method Pets.CreateApInPropertiesWithApstring. -type PetsCreateApInPropertiesWithApstringResponse struct { - PetApInPropertiesWithApstring *PetApInPropertiesWithApstring - - // RawResponse contains the underlying HTTP response. - RawResponse *http.Response -} - -// PetsCreateApObjectResponse contains the response from method Pets.CreateApObject. -type PetsCreateApObjectResponse struct { - PetApObject *PetApObject - - // RawResponse contains the underlying HTTP response. - RawResponse *http.Response -} - -// PetsCreateApStringResponse contains the response from method Pets.CreateApString. -type PetsCreateApStringResponse struct { - PetApString *PetApString - - // RawResponse contains the underlying HTTP response. - RawResponse *http.Response -} - -// PetsCreateApTrueResponse contains the response from method Pets.CreateApTrue. -type PetsCreateApTrueResponse struct { - PetApTrue *PetApTrue - - // RawResponse contains the underlying HTTP response. - RawResponse *http.Response -} - -// PetsCreateCatApTrueResponse contains the response from method Pets.CreateCatApTrue. -type PetsCreateCatApTrueResponse struct { - CatApTrue *CatApTrue - - // RawResponse contains the underlying HTTP response. - RawResponse *http.Response -} diff --git a/test/autorest/generated/additionalpropertiesgroup/internal/additionalpropertiesgroup/pets.go b/test/autorest/generated/additionalpropertiesgroup/internal/additionalpropertiesgroup/pets.go deleted file mode 100644 index c9ba4ba20..000000000 --- a/test/autorest/generated/additionalpropertiesgroup/internal/additionalpropertiesgroup/pets.go +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. -// Code generated by Microsoft (R) AutoRest Code Generator. -// Changes may cause incorrect behavior and will be lost if the code is regenerated. - -package additionalpropertiesgroup - -import ( - "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "net/http" - "net/url" - "path" -) - -type PetsOperations struct{} - -// CreateApInPropertiesCreateRequest creates the CreateApInProperties request. -func (PetsOperations) CreateApInPropertiesCreateRequest(u url.URL, createParameters PetApInProperties) (*azcore.Request, error) { - urlPath := "/additionalProperties/in/properties" - u.Path = path.Join(u.Path, urlPath) - req := azcore.NewRequest(http.MethodPut, u) - err := req.MarshalAsJSON(createParameters) - if err != nil { - return nil, err - } - return req, nil -} - -// CreateApInPropertiesHandleResponse handles the CreateApInProperties response. -func (PetsOperations) CreateApInPropertiesHandleResponse(resp *azcore.Response) (*PetsCreateApInPropertiesResponse, error) { - if !resp.HasStatusCode(http.StatusOK) { - return nil, newError(resp) - } - result := PetsCreateApInPropertiesResponse{RawResponse: resp.Response} - return &result, resp.UnmarshalAsJSON(&result.PetApInProperties) -} - -// CreateApInPropertiesWithApstringCreateRequest creates the CreateApInPropertiesWithApstring request. -func (PetsOperations) CreateApInPropertiesWithApstringCreateRequest(u url.URL, createParameters PetApInPropertiesWithApstring) (*azcore.Request, error) { - urlPath := "/additionalProperties/in/properties/with/additionalProperties/string" - u.Path = path.Join(u.Path, urlPath) - req := azcore.NewRequest(http.MethodPut, u) - err := req.MarshalAsJSON(createParameters) - if err != nil { - return nil, err - } - return req, nil -} - -// CreateApInPropertiesWithApstringHandleResponse handles the CreateApInPropertiesWithApstring response. -func (PetsOperations) CreateApInPropertiesWithApstringHandleResponse(resp *azcore.Response) (*PetsCreateApInPropertiesWithApstringResponse, error) { - if !resp.HasStatusCode(http.StatusOK) { - return nil, newError(resp) - } - result := PetsCreateApInPropertiesWithApstringResponse{RawResponse: resp.Response} - return &result, resp.UnmarshalAsJSON(&result.PetApInPropertiesWithApstring) -} - -// CreateApObjectCreateRequest creates the CreateApObject request. -func (PetsOperations) CreateApObjectCreateRequest(u url.URL, createParameters PetApObject) (*azcore.Request, error) { - urlPath := "/additionalProperties/type/object" - u.Path = path.Join(u.Path, urlPath) - req := azcore.NewRequest(http.MethodPut, u) - err := req.MarshalAsJSON(createParameters) - if err != nil { - return nil, err - } - return req, nil -} - -// CreateApObjectHandleResponse handles the CreateApObject response. -func (PetsOperations) CreateApObjectHandleResponse(resp *azcore.Response) (*PetsCreateApObjectResponse, error) { - if !resp.HasStatusCode(http.StatusOK) { - return nil, newError(resp) - } - result := PetsCreateApObjectResponse{RawResponse: resp.Response} - return &result, resp.UnmarshalAsJSON(&result.PetApObject) -} - -// CreateApStringCreateRequest creates the CreateApString request. -func (PetsOperations) CreateApStringCreateRequest(u url.URL, createParameters PetApString) (*azcore.Request, error) { - urlPath := "/additionalProperties/type/string" - u.Path = path.Join(u.Path, urlPath) - req := azcore.NewRequest(http.MethodPut, u) - err := req.MarshalAsJSON(createParameters) - if err != nil { - return nil, err - } - return req, nil -} - -// CreateApStringHandleResponse handles the CreateApString response. -func (PetsOperations) CreateApStringHandleResponse(resp *azcore.Response) (*PetsCreateApStringResponse, error) { - if !resp.HasStatusCode(http.StatusOK) { - return nil, newError(resp) - } - result := PetsCreateApStringResponse{RawResponse: resp.Response} - return &result, resp.UnmarshalAsJSON(&result.PetApString) -} - -// CreateApTrueCreateRequest creates the CreateApTrue request. -func (PetsOperations) CreateApTrueCreateRequest(u url.URL, createParameters PetApTrue) (*azcore.Request, error) { - urlPath := "/additionalProperties/true" - u.Path = path.Join(u.Path, urlPath) - req := azcore.NewRequest(http.MethodPut, u) - err := req.MarshalAsJSON(createParameters) - if err != nil { - return nil, err - } - return req, nil -} - -// CreateApTrueHandleResponse handles the CreateApTrue response. -func (PetsOperations) CreateApTrueHandleResponse(resp *azcore.Response) (*PetsCreateApTrueResponse, error) { - if !resp.HasStatusCode(http.StatusOK) { - return nil, newError(resp) - } - result := PetsCreateApTrueResponse{RawResponse: resp.Response} - return &result, resp.UnmarshalAsJSON(&result.PetApTrue) -} - -// CreateCatApTrueCreateRequest creates the CreateCatApTrue request. -func (PetsOperations) CreateCatApTrueCreateRequest(u url.URL, createParameters CatApTrue) (*azcore.Request, error) { - urlPath := "/additionalProperties/true-subclass" - u.Path = path.Join(u.Path, urlPath) - req := azcore.NewRequest(http.MethodPut, u) - err := req.MarshalAsJSON(createParameters) - if err != nil { - return nil, err - } - return req, nil -} - -// CreateCatApTrueHandleResponse handles the CreateCatApTrue response. -func (PetsOperations) CreateCatApTrueHandleResponse(resp *azcore.Response) (*PetsCreateCatApTrueResponse, error) { - if !resp.HasStatusCode(http.StatusOK) { - return nil, newError(resp) - } - result := PetsCreateCatApTrueResponse{RawResponse: resp.Response} - return &result, resp.UnmarshalAsJSON(&result.CatApTrue) -} diff --git a/test/autorest/generated/additionalpropertiesgroup/models.go b/test/autorest/generated/additionalpropertiesgroup/models.go deleted file mode 100644 index 4278b77e3..000000000 --- a/test/autorest/generated/additionalpropertiesgroup/models.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. -// Code generated by Microsoft (R) AutoRest Code Generator. -// Changes may cause incorrect behavior and will be lost if the code is regenerated. - -package additionalpropertiesgroup - -import azinternal "generatortests/autorest/generated/additionalpropertiesgroup/internal/additionalpropertiesgroup" - -type CatApTrue = azinternal.CatApTrue - -type Error = azinternal.Error - -type PetApInProperties = azinternal.PetApInProperties - -type PetApInPropertiesWithApstring = azinternal.PetApInPropertiesWithApstring - -type PetApObject = azinternal.PetApObject - -type PetApString = azinternal.PetApString - -type PetApTrue = azinternal.PetApTrue - -// PetsCreateApInPropertiesResponse contains the response from method Pets.CreateApInProperties. -type PetsCreateApInPropertiesResponse = azinternal.PetsCreateApInPropertiesResponse - -// PetsCreateApInPropertiesWithApstringResponse contains the response from method Pets.CreateApInPropertiesWithApstring. -type PetsCreateApInPropertiesWithApstringResponse = azinternal.PetsCreateApInPropertiesWithApstringResponse - -// PetsCreateApObjectResponse contains the response from method Pets.CreateApObject. -type PetsCreateApObjectResponse = azinternal.PetsCreateApObjectResponse - -// PetsCreateApStringResponse contains the response from method Pets.CreateApString. -type PetsCreateApStringResponse = azinternal.PetsCreateApStringResponse - -// PetsCreateApTrueResponse contains the response from method Pets.CreateApTrue. -type PetsCreateApTrueResponse = azinternal.PetsCreateApTrueResponse - -// PetsCreateCatApTrueResponse contains the response from method Pets.CreateCatApTrue. -type PetsCreateCatApTrueResponse = azinternal.PetsCreateCatApTrueResponse diff --git a/test/autorest/generated/additionalpropertiesgroup/pets.go b/test/autorest/generated/additionalpropertiesgroup/pets.go deleted file mode 100644 index c3f74b64d..000000000 --- a/test/autorest/generated/additionalpropertiesgroup/pets.go +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. -// Code generated by Microsoft (R) AutoRest Code Generator. -// Changes may cause incorrect behavior and will be lost if the code is regenerated. - -package additionalpropertiesgroup - -import ( - "context" - azinternal "generatortests/autorest/generated/additionalpropertiesgroup/internal/additionalpropertiesgroup" -) - -// PetsOperations contains the methods for the Pets group. -type PetsOperations interface { - // CreateApInProperties - Create a Pet which contains more properties than what is defined. - CreateApInProperties(ctx context.Context, createParameters PetApInProperties) (*PetsCreateApInPropertiesResponse, error) - // CreateApInPropertiesWithApstring - Create a Pet which contains more properties than what is defined. - CreateApInPropertiesWithApstring(ctx context.Context, createParameters PetApInPropertiesWithApstring) (*PetsCreateApInPropertiesWithApstringResponse, error) - // CreateApObject - Create a Pet which contains more properties than what is defined. - CreateApObject(ctx context.Context, createParameters PetApObject) (*PetsCreateApObjectResponse, error) - // CreateApString - Create a Pet which contains more properties than what is defined. - CreateApString(ctx context.Context, createParameters PetApString) (*PetsCreateApStringResponse, error) - // CreateApTrue - Create a Pet which contains more properties than what is defined. - CreateApTrue(ctx context.Context, createParameters PetApTrue) (*PetsCreateApTrueResponse, error) - // CreateCatApTrue - Create a CatAPTrue which contains more properties than what is defined. - CreateCatApTrue(ctx context.Context, createParameters CatApTrue) (*PetsCreateCatApTrueResponse, error) -} - -type petsOperations struct { - *Client - azinternal.PetsOperations -} - -// CreateApInProperties - Create a Pet which contains more properties than what is defined. -func (client *petsOperations) CreateApInProperties(ctx context.Context, createParameters PetApInProperties) (*PetsCreateApInPropertiesResponse, error) { - req, err := client.CreateApInPropertiesCreateRequest(*client.u, createParameters) - if err != nil { - return nil, err - } - resp, err := client.p.Do(ctx, req) - if err != nil { - return nil, err - } - result, err := client.CreateApInPropertiesHandleResponse(resp) - if err != nil { - return nil, err - } - return result, nil -} - -// CreateApInPropertiesWithApstring - Create a Pet which contains more properties than what is defined. -func (client *petsOperations) CreateApInPropertiesWithApstring(ctx context.Context, createParameters PetApInPropertiesWithApstring) (*PetsCreateApInPropertiesWithApstringResponse, error) { - req, err := client.CreateApInPropertiesWithApstringCreateRequest(*client.u, createParameters) - if err != nil { - return nil, err - } - resp, err := client.p.Do(ctx, req) - if err != nil { - return nil, err - } - result, err := client.CreateApInPropertiesWithApstringHandleResponse(resp) - if err != nil { - return nil, err - } - return result, nil -} - -// CreateApObject - Create a Pet which contains more properties than what is defined. -func (client *petsOperations) CreateApObject(ctx context.Context, createParameters PetApObject) (*PetsCreateApObjectResponse, error) { - req, err := client.CreateApObjectCreateRequest(*client.u, createParameters) - if err != nil { - return nil, err - } - resp, err := client.p.Do(ctx, req) - if err != nil { - return nil, err - } - result, err := client.CreateApObjectHandleResponse(resp) - if err != nil { - return nil, err - } - return result, nil -} - -// CreateApString - Create a Pet which contains more properties than what is defined. -func (client *petsOperations) CreateApString(ctx context.Context, createParameters PetApString) (*PetsCreateApStringResponse, error) { - req, err := client.CreateApStringCreateRequest(*client.u, createParameters) - if err != nil { - return nil, err - } - resp, err := client.p.Do(ctx, req) - if err != nil { - return nil, err - } - result, err := client.CreateApStringHandleResponse(resp) - if err != nil { - return nil, err - } - return result, nil -} - -// CreateApTrue - Create a Pet which contains more properties than what is defined. -func (client *petsOperations) CreateApTrue(ctx context.Context, createParameters PetApTrue) (*PetsCreateApTrueResponse, error) { - req, err := client.CreateApTrueCreateRequest(*client.u, createParameters) - if err != nil { - return nil, err - } - resp, err := client.p.Do(ctx, req) - if err != nil { - return nil, err - } - result, err := client.CreateApTrueHandleResponse(resp) - if err != nil { - return nil, err - } - return result, nil -} - -// CreateCatApTrue - Create a CatAPTrue which contains more properties than what is defined. -func (client *petsOperations) CreateCatApTrue(ctx context.Context, createParameters CatApTrue) (*PetsCreateCatApTrueResponse, error) { - req, err := client.CreateCatApTrueCreateRequest(*client.u, createParameters) - if err != nil { - return nil, err - } - resp, err := client.p.Do(ctx, req) - if err != nil { - return nil, err - } - result, err := client.CreateCatApTrueHandleResponse(resp) - if err != nil { - return nil, err - } - return result, nil -} - -var _ PetsOperations = (*petsOperations)(nil) diff --git a/test/autorest/generated/additionalpropertiesgroup/client.go b/test/autorest/generated/additionalpropsgroup/client.go similarity index 91% rename from test/autorest/generated/additionalpropertiesgroup/client.go rename to test/autorest/generated/additionalpropsgroup/client.go index ed8d7e2d0..47161aaed 100644 --- a/test/autorest/generated/additionalpropertiesgroup/client.go +++ b/test/autorest/generated/additionalpropsgroup/client.go @@ -3,13 +3,15 @@ // Code generated by Microsoft (R) AutoRest Code Generator. // Changes may cause incorrect behavior and will be lost if the code is regenerated. -package additionalpropertiesgroup +package additionalpropsgroup import ( + "fmt" "github.com/Azure/azure-sdk-for-go/sdk/azcore" "net/url" ) +// ClientOptions contains configuration settings for the default client's pipeline. type ClientOptions struct { // HTTPClient sets the transport for making HTTP requests. HTTPClient azcore.Transport @@ -63,6 +65,9 @@ func NewClientWithPipeline(endpoint string, p azcore.Pipeline) (*Client, error) if err != nil { return nil, err } + if u.Scheme == "" { + return nil, fmt.Errorf("no scheme detected in endpoint %s", endpoint) + } return &Client{u: u, p: p}, nil } diff --git a/test/autorest/generated/additionalpropsgroup/models.go b/test/autorest/generated/additionalpropsgroup/models.go new file mode 100644 index 000000000..5ffc43b62 --- /dev/null +++ b/test/autorest/generated/additionalpropsgroup/models.go @@ -0,0 +1,430 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package additionalpropsgroup + +import ( + "encoding/json" + "fmt" + "net/http" +) + +type CatApTrue struct { + PetApTrue + Friendly *bool `json:"friendly,omitempty"` +} + +func (c CatApTrue) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if c.ID != nil { + objectMap["id"] = c.ID + } + if c.Name != nil { + objectMap["name"] = c.Name + } + if c.Status != nil { + objectMap["status"] = c.Status + } + if c.Friendly != nil { + objectMap["friendly"] = c.Friendly + } + if c.AdditionalProperties != nil { + for k, v := range *c.AdditionalProperties { + objectMap[k] = v + } + } + return json.Marshal(objectMap) +} + +func (c *CatApTrue) UnmarshalJSON(data []byte) error { + var rawMsg map[string]*json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return err + } + for k, v := range rawMsg { + var err error + switch k { + case "id": + if v != nil { + err = json.Unmarshal(*v, &c.ID) + } + case "name": + if v != nil { + err = json.Unmarshal(*v, &c.Name) + } + case "status": + if v != nil { + err = json.Unmarshal(*v, &c.Status) + } + case "friendly": + if v != nil { + err = json.Unmarshal(*v, &c.Friendly) + } + default: + if c.AdditionalProperties == nil { + c.AdditionalProperties = &map[string]interface{}{} + } + if v != nil { + var aux interface{} + err = json.Unmarshal(*v, &aux) + (*c.AdditionalProperties)[k] = aux + } + } + if err != nil { + return err + } + } + return nil +} + +// CatApTrueResponse is the response envelope for operations that return a CatApTrue type. +type CatApTrueResponse struct { + CatApTrue *CatApTrue + + // RawResponse contains the underlying HTTP response. + RawResponse *http.Response +} + +type Error struct { + Message *string `json:"message,omitempty"` + Status *int32 `json:"status,omitempty"` +} + +func (e Error) Error() string { + msg := "" + if e.Message != nil { + msg += fmt.Sprintf("Message: %v\n", *e.Message) + } + if e.Status != nil { + msg += fmt.Sprintf("Status: %v\n", *e.Status) + } + if msg == "" { + msg = "missing error info" + } + return msg +} + +type PetApInProperties struct { + // Dictionary of + AdditionalProperties *map[string]float32 `json:"additionalProperties,omitempty"` + ID *int32 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Status *bool `json:"status,omitempty"` +} + +// PetApInPropertiesResponse is the response envelope for operations that return a PetApInProperties type. +type PetApInPropertiesResponse struct { + PetApInProperties *PetApInProperties + + // RawResponse contains the underlying HTTP response. + RawResponse *http.Response +} + +type PetApInPropertiesWithApstring struct { + // Contains additional key/value pairs not defined in the schema. + AdditionalProperties *map[string]string + + // Dictionary of + AdditionalProperties1 *map[string]float32 `json:"additionalProperties,omitempty"` + ID *int32 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + OdataLocation *string `json:"@odata.location,omitempty"` + Status *bool `json:"status,omitempty"` +} + +func (p PetApInPropertiesWithApstring) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if p.AdditionalProperties1 != nil { + objectMap["additionalProperties"] = p.AdditionalProperties1 + } + if p.ID != nil { + objectMap["id"] = p.ID + } + if p.Name != nil { + objectMap["name"] = p.Name + } + if p.OdataLocation != nil { + objectMap["@odata.location"] = p.OdataLocation + } + if p.Status != nil { + objectMap["status"] = p.Status + } + if p.AdditionalProperties != nil { + for k, v := range *p.AdditionalProperties { + objectMap[k] = v + } + } + return json.Marshal(objectMap) +} + +func (p *PetApInPropertiesWithApstring) UnmarshalJSON(data []byte) error { + var rawMsg map[string]*json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return err + } + for k, v := range rawMsg { + var err error + switch k { + case "additionalProperties": + if v != nil { + err = json.Unmarshal(*v, &p.AdditionalProperties1) + } + case "id": + if v != nil { + err = json.Unmarshal(*v, &p.ID) + } + case "name": + if v != nil { + err = json.Unmarshal(*v, &p.Name) + } + case "@odata.location": + if v != nil { + err = json.Unmarshal(*v, &p.OdataLocation) + } + case "status": + if v != nil { + err = json.Unmarshal(*v, &p.Status) + } + default: + if p.AdditionalProperties == nil { + p.AdditionalProperties = &map[string]string{} + } + if v != nil { + var aux string + err = json.Unmarshal(*v, &aux) + (*p.AdditionalProperties)[k] = aux + } + } + if err != nil { + return err + } + } + return nil +} + +// PetApInPropertiesWithApstringResponse is the response envelope for operations that return a PetApInPropertiesWithApstring +// type. +type PetApInPropertiesWithApstringResponse struct { + PetApInPropertiesWithApstring *PetApInPropertiesWithApstring + + // RawResponse contains the underlying HTTP response. + RawResponse *http.Response +} + +type PetApObject struct { + // Contains additional key/value pairs not defined in the schema. + AdditionalProperties *map[string]interface{} + ID *int32 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Status *bool `json:"status,omitempty"` +} + +func (p PetApObject) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if p.ID != nil { + objectMap["id"] = p.ID + } + if p.Name != nil { + objectMap["name"] = p.Name + } + if p.Status != nil { + objectMap["status"] = p.Status + } + if p.AdditionalProperties != nil { + for k, v := range *p.AdditionalProperties { + objectMap[k] = v + } + } + return json.Marshal(objectMap) +} + +func (p *PetApObject) UnmarshalJSON(data []byte) error { + var rawMsg map[string]*json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return err + } + for k, v := range rawMsg { + var err error + switch k { + case "id": + if v != nil { + err = json.Unmarshal(*v, &p.ID) + } + case "name": + if v != nil { + err = json.Unmarshal(*v, &p.Name) + } + case "status": + if v != nil { + err = json.Unmarshal(*v, &p.Status) + } + default: + if p.AdditionalProperties == nil { + p.AdditionalProperties = &map[string]interface{}{} + } + if v != nil { + var aux interface{} + err = json.Unmarshal(*v, &aux) + (*p.AdditionalProperties)[k] = aux + } + } + if err != nil { + return err + } + } + return nil +} + +// PetApObjectResponse is the response envelope for operations that return a PetApObject type. +type PetApObjectResponse struct { + PetApObject *PetApObject + + // RawResponse contains the underlying HTTP response. + RawResponse *http.Response +} + +type PetApString struct { + // Contains additional key/value pairs not defined in the schema. + AdditionalProperties *map[string]string + ID *int32 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Status *bool `json:"status,omitempty"` +} + +func (p PetApString) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if p.ID != nil { + objectMap["id"] = p.ID + } + if p.Name != nil { + objectMap["name"] = p.Name + } + if p.Status != nil { + objectMap["status"] = p.Status + } + if p.AdditionalProperties != nil { + for k, v := range *p.AdditionalProperties { + objectMap[k] = v + } + } + return json.Marshal(objectMap) +} + +func (p *PetApString) UnmarshalJSON(data []byte) error { + var rawMsg map[string]*json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return err + } + for k, v := range rawMsg { + var err error + switch k { + case "id": + if v != nil { + err = json.Unmarshal(*v, &p.ID) + } + case "name": + if v != nil { + err = json.Unmarshal(*v, &p.Name) + } + case "status": + if v != nil { + err = json.Unmarshal(*v, &p.Status) + } + default: + if p.AdditionalProperties == nil { + p.AdditionalProperties = &map[string]string{} + } + if v != nil { + var aux string + err = json.Unmarshal(*v, &aux) + (*p.AdditionalProperties)[k] = aux + } + } + if err != nil { + return err + } + } + return nil +} + +// PetApStringResponse is the response envelope for operations that return a PetApString type. +type PetApStringResponse struct { + PetApString *PetApString + + // RawResponse contains the underlying HTTP response. + RawResponse *http.Response +} + +type PetApTrue struct { + // Contains additional key/value pairs not defined in the schema. + AdditionalProperties *map[string]interface{} + ID *int32 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Status *bool `json:"status,omitempty"` +} + +func (p PetApTrue) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if p.ID != nil { + objectMap["id"] = p.ID + } + if p.Name != nil { + objectMap["name"] = p.Name + } + if p.Status != nil { + objectMap["status"] = p.Status + } + if p.AdditionalProperties != nil { + for k, v := range *p.AdditionalProperties { + objectMap[k] = v + } + } + return json.Marshal(objectMap) +} + +func (p *PetApTrue) UnmarshalJSON(data []byte) error { + var rawMsg map[string]*json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return err + } + for k, v := range rawMsg { + var err error + switch k { + case "id": + if v != nil { + err = json.Unmarshal(*v, &p.ID) + } + case "name": + if v != nil { + err = json.Unmarshal(*v, &p.Name) + } + case "status": + if v != nil { + err = json.Unmarshal(*v, &p.Status) + } + default: + if p.AdditionalProperties == nil { + p.AdditionalProperties = &map[string]interface{}{} + } + if v != nil { + var aux interface{} + err = json.Unmarshal(*v, &aux) + (*p.AdditionalProperties)[k] = aux + } + } + if err != nil { + return err + } + } + return nil +} + +// PetApTrueResponse is the response envelope for operations that return a PetApTrue type. +type PetApTrueResponse struct { + PetApTrue *PetApTrue + + // RawResponse contains the underlying HTTP response. + RawResponse *http.Response +} diff --git a/test/autorest/generated/additionalpropsgroup/pets.go b/test/autorest/generated/additionalpropsgroup/pets.go new file mode 100644 index 000000000..b8b34fff7 --- /dev/null +++ b/test/autorest/generated/additionalpropsgroup/pets.go @@ -0,0 +1,309 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package additionalpropsgroup + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "net/http" +) + +// PetsOperations contains the methods for the Pets group. +type PetsOperations interface { + // CreateApInProperties - Create a Pet which contains more properties than what is defined. + CreateApInProperties(ctx context.Context, createParameters PetApInProperties) (*PetApInPropertiesResponse, error) + // CreateApInPropertiesWithApstring - Create a Pet which contains more properties than what is defined. + CreateApInPropertiesWithApstring(ctx context.Context, createParameters PetApInPropertiesWithApstring) (*PetApInPropertiesWithApstringResponse, error) + // CreateApObject - Create a Pet which contains more properties than what is defined. + CreateApObject(ctx context.Context, createParameters PetApObject) (*PetApObjectResponse, error) + // CreateApString - Create a Pet which contains more properties than what is defined. + CreateApString(ctx context.Context, createParameters PetApString) (*PetApStringResponse, error) + // CreateApTrue - Create a Pet which contains more properties than what is defined. + CreateApTrue(ctx context.Context, createParameters PetApTrue) (*PetApTrueResponse, error) + // CreateCatApTrue - Create a CatAPTrue which contains more properties than what is defined. + CreateCatApTrue(ctx context.Context, createParameters CatApTrue) (*CatApTrueResponse, error) +} + +// petsOperations implements the PetsOperations interface. +type petsOperations struct { + *Client +} + +// CreateApInProperties - Create a Pet which contains more properties than what is defined. +func (client *petsOperations) CreateApInProperties(ctx context.Context, createParameters PetApInProperties) (*PetApInPropertiesResponse, error) { + req, err := client.createApInPropertiesCreateRequest(createParameters) + if err != nil { + return nil, err + } + resp, err := client.p.Do(ctx, req) + if err != nil { + return nil, err + } + result, err := client.createApInPropertiesHandleResponse(resp) + if err != nil { + return nil, err + } + return result, nil +} + +// createApInPropertiesCreateRequest creates the CreateApInProperties request. +func (client *petsOperations) createApInPropertiesCreateRequest(createParameters PetApInProperties) (*azcore.Request, error) { + urlPath := "/additionalProperties/in/properties" + u, err := client.u.Parse(urlPath) + if err != nil { + return nil, err + } + req := azcore.NewRequest(http.MethodPut, *u) + return req, req.MarshalAsJSON(createParameters) +} + +// createApInPropertiesHandleResponse handles the CreateApInProperties response. +func (client *petsOperations) createApInPropertiesHandleResponse(resp *azcore.Response) (*PetApInPropertiesResponse, error) { + if !resp.HasStatusCode(http.StatusOK) { + return nil, client.createApInPropertiesHandleError(resp) + } + result := PetApInPropertiesResponse{RawResponse: resp.Response} + return &result, resp.UnmarshalAsJSON(&result.PetApInProperties) +} + +// createApInPropertiesHandleError handles the CreateApInProperties error response. +func (client *petsOperations) createApInPropertiesHandleError(resp *azcore.Response) error { + var err Error + if err := resp.UnmarshalAsJSON(&err); err != nil { + return err + } + return err +} + +// CreateApInPropertiesWithApstring - Create a Pet which contains more properties than what is defined. +func (client *petsOperations) CreateApInPropertiesWithApstring(ctx context.Context, createParameters PetApInPropertiesWithApstring) (*PetApInPropertiesWithApstringResponse, error) { + req, err := client.createApInPropertiesWithApstringCreateRequest(createParameters) + if err != nil { + return nil, err + } + resp, err := client.p.Do(ctx, req) + if err != nil { + return nil, err + } + result, err := client.createApInPropertiesWithApstringHandleResponse(resp) + if err != nil { + return nil, err + } + return result, nil +} + +// createApInPropertiesWithApstringCreateRequest creates the CreateApInPropertiesWithApstring request. +func (client *petsOperations) createApInPropertiesWithApstringCreateRequest(createParameters PetApInPropertiesWithApstring) (*azcore.Request, error) { + urlPath := "/additionalProperties/in/properties/with/additionalProperties/string" + u, err := client.u.Parse(urlPath) + if err != nil { + return nil, err + } + req := azcore.NewRequest(http.MethodPut, *u) + return req, req.MarshalAsJSON(createParameters) +} + +// createApInPropertiesWithApstringHandleResponse handles the CreateApInPropertiesWithApstring response. +func (client *petsOperations) createApInPropertiesWithApstringHandleResponse(resp *azcore.Response) (*PetApInPropertiesWithApstringResponse, error) { + if !resp.HasStatusCode(http.StatusOK) { + return nil, client.createApInPropertiesWithApstringHandleError(resp) + } + result := PetApInPropertiesWithApstringResponse{RawResponse: resp.Response} + return &result, resp.UnmarshalAsJSON(&result.PetApInPropertiesWithApstring) +} + +// createApInPropertiesWithApstringHandleError handles the CreateApInPropertiesWithApstring error response. +func (client *petsOperations) createApInPropertiesWithApstringHandleError(resp *azcore.Response) error { + var err Error + if err := resp.UnmarshalAsJSON(&err); err != nil { + return err + } + return err +} + +// CreateApObject - Create a Pet which contains more properties than what is defined. +func (client *petsOperations) CreateApObject(ctx context.Context, createParameters PetApObject) (*PetApObjectResponse, error) { + req, err := client.createApObjectCreateRequest(createParameters) + if err != nil { + return nil, err + } + resp, err := client.p.Do(ctx, req) + if err != nil { + return nil, err + } + result, err := client.createApObjectHandleResponse(resp) + if err != nil { + return nil, err + } + return result, nil +} + +// createApObjectCreateRequest creates the CreateApObject request. +func (client *petsOperations) createApObjectCreateRequest(createParameters PetApObject) (*azcore.Request, error) { + urlPath := "/additionalProperties/type/object" + u, err := client.u.Parse(urlPath) + if err != nil { + return nil, err + } + req := azcore.NewRequest(http.MethodPut, *u) + return req, req.MarshalAsJSON(createParameters) +} + +// createApObjectHandleResponse handles the CreateApObject response. +func (client *petsOperations) createApObjectHandleResponse(resp *azcore.Response) (*PetApObjectResponse, error) { + if !resp.HasStatusCode(http.StatusOK) { + return nil, client.createApObjectHandleError(resp) + } + result := PetApObjectResponse{RawResponse: resp.Response} + return &result, resp.UnmarshalAsJSON(&result.PetApObject) +} + +// createApObjectHandleError handles the CreateApObject error response. +func (client *petsOperations) createApObjectHandleError(resp *azcore.Response) error { + var err Error + if err := resp.UnmarshalAsJSON(&err); err != nil { + return err + } + return err +} + +// CreateApString - Create a Pet which contains more properties than what is defined. +func (client *petsOperations) CreateApString(ctx context.Context, createParameters PetApString) (*PetApStringResponse, error) { + req, err := client.createApStringCreateRequest(createParameters) + if err != nil { + return nil, err + } + resp, err := client.p.Do(ctx, req) + if err != nil { + return nil, err + } + result, err := client.createApStringHandleResponse(resp) + if err != nil { + return nil, err + } + return result, nil +} + +// createApStringCreateRequest creates the CreateApString request. +func (client *petsOperations) createApStringCreateRequest(createParameters PetApString) (*azcore.Request, error) { + urlPath := "/additionalProperties/type/string" + u, err := client.u.Parse(urlPath) + if err != nil { + return nil, err + } + req := azcore.NewRequest(http.MethodPut, *u) + return req, req.MarshalAsJSON(createParameters) +} + +// createApStringHandleResponse handles the CreateApString response. +func (client *petsOperations) createApStringHandleResponse(resp *azcore.Response) (*PetApStringResponse, error) { + if !resp.HasStatusCode(http.StatusOK) { + return nil, client.createApStringHandleError(resp) + } + result := PetApStringResponse{RawResponse: resp.Response} + return &result, resp.UnmarshalAsJSON(&result.PetApString) +} + +// createApStringHandleError handles the CreateApString error response. +func (client *petsOperations) createApStringHandleError(resp *azcore.Response) error { + var err Error + if err := resp.UnmarshalAsJSON(&err); err != nil { + return err + } + return err +} + +// CreateApTrue - Create a Pet which contains more properties than what is defined. +func (client *petsOperations) CreateApTrue(ctx context.Context, createParameters PetApTrue) (*PetApTrueResponse, error) { + req, err := client.createApTrueCreateRequest(createParameters) + if err != nil { + return nil, err + } + resp, err := client.p.Do(ctx, req) + if err != nil { + return nil, err + } + result, err := client.createApTrueHandleResponse(resp) + if err != nil { + return nil, err + } + return result, nil +} + +// createApTrueCreateRequest creates the CreateApTrue request. +func (client *petsOperations) createApTrueCreateRequest(createParameters PetApTrue) (*azcore.Request, error) { + urlPath := "/additionalProperties/true" + u, err := client.u.Parse(urlPath) + if err != nil { + return nil, err + } + req := azcore.NewRequest(http.MethodPut, *u) + return req, req.MarshalAsJSON(createParameters) +} + +// createApTrueHandleResponse handles the CreateApTrue response. +func (client *petsOperations) createApTrueHandleResponse(resp *azcore.Response) (*PetApTrueResponse, error) { + if !resp.HasStatusCode(http.StatusOK) { + return nil, client.createApTrueHandleError(resp) + } + result := PetApTrueResponse{RawResponse: resp.Response} + return &result, resp.UnmarshalAsJSON(&result.PetApTrue) +} + +// createApTrueHandleError handles the CreateApTrue error response. +func (client *petsOperations) createApTrueHandleError(resp *azcore.Response) error { + var err Error + if err := resp.UnmarshalAsJSON(&err); err != nil { + return err + } + return err +} + +// CreateCatApTrue - Create a CatAPTrue which contains more properties than what is defined. +func (client *petsOperations) CreateCatApTrue(ctx context.Context, createParameters CatApTrue) (*CatApTrueResponse, error) { + req, err := client.createCatApTrueCreateRequest(createParameters) + if err != nil { + return nil, err + } + resp, err := client.p.Do(ctx, req) + if err != nil { + return nil, err + } + result, err := client.createCatApTrueHandleResponse(resp) + if err != nil { + return nil, err + } + return result, nil +} + +// createCatApTrueCreateRequest creates the CreateCatApTrue request. +func (client *petsOperations) createCatApTrueCreateRequest(createParameters CatApTrue) (*azcore.Request, error) { + urlPath := "/additionalProperties/true-subclass" + u, err := client.u.Parse(urlPath) + if err != nil { + return nil, err + } + req := azcore.NewRequest(http.MethodPut, *u) + return req, req.MarshalAsJSON(createParameters) +} + +// createCatApTrueHandleResponse handles the CreateCatApTrue response. +func (client *petsOperations) createCatApTrueHandleResponse(resp *azcore.Response) (*CatApTrueResponse, error) { + if !resp.HasStatusCode(http.StatusOK) { + return nil, client.createCatApTrueHandleError(resp) + } + result := CatApTrueResponse{RawResponse: resp.Response} + return &result, resp.UnmarshalAsJSON(&result.CatApTrue) +} + +// createCatApTrueHandleError handles the CreateCatApTrue error response. +func (client *petsOperations) createCatApTrueHandleError(resp *azcore.Response) error { + var err Error + if err := resp.UnmarshalAsJSON(&err); err != nil { + return err + } + return err +} diff --git a/test/autorest/generated/complexgroup/models.go b/test/autorest/generated/complexgroup/models.go index 6ba36aa12..1d01d0d09 100644 --- a/test/autorest/generated/complexgroup/models.go +++ b/test/autorest/generated/complexgroup/models.go @@ -866,7 +866,9 @@ type SiameseResponse struct { type SmartSalmon struct { Salmon - CollegeDegree *string `json:"college_degree,omitempty"` + // Contains additional key/value pairs not defined in the schema. + AdditionalProperties *map[string]interface{} + CollegeDegree *string `json:"college_degree,omitempty"` } func (s SmartSalmon) MarshalJSON() ([]byte, error) { diff --git a/test/storage/2019-07-07/azblob/models.go b/test/storage/2019-07-07/azblob/models.go index cc51deba0..b9e090fa8 100644 --- a/test/storage/2019-07-07/azblob/models.go +++ b/test/storage/2019-07-07/azblob/models.go @@ -897,7 +897,9 @@ type BlobItem struct { } type BlobMetadata struct { - Encrypted *string `xml:"Encrypted,attr"` + // Contains additional key/value pairs not defined in the schema. + AdditionalProperties *map[string]string + Encrypted *string `xml:"Encrypted,attr"` } type BlobPrefix struct {