in packages/codegen.go/src/models.ts [424:530]
function generateJSONUnmarshallerBody(modelType: go.ModelType | go.PolymorphicType, modelDef: ModelDef, receiver: string, imports: ImportManager, options: go.Options): string {
const emitAddlProps = function (tab: string, addlProps: go.MapType): string {
let addlPropsText = `${tab}\t\tif ${receiver}.AdditionalProperties == nil {\n`;
let ref = '';
if (!addlProps.valueTypeByValue) {
ref = '&';
}
addlPropsText += `${tab}\t\t\t${receiver}.AdditionalProperties = ${go.getTypeDeclaration(addlProps)}{}\n`;
addlPropsText += `${tab}\t\t}\n`;
addlPropsText += `${tab}\t\tif val != nil {\n`;
let auxType = go.getTypeDeclaration(addlProps.valueType);
let assignment = `${ref}aux`;
if (go.isTimeType(addlProps.valueType)) {
imports.add('time');
auxType = addlProps.valueType.dateTimeFormat!;
assignment = `(*time.Time)(${assignment})`;
}
addlPropsText += `${tab}\t\t\tvar aux ${auxType}\n`;
addlPropsText += `${tab}\t\t\terr = json.Unmarshal(val, &aux)\n`;
addlPropsText += `${tab}\t\t\t${receiver}.AdditionalProperties[key] = ${assignment}\n`;
addlPropsText += `${tab}\t\t}\n`;
addlPropsText += `${tab}\t\tdelete(rawMsg, key)\n`;
return addlPropsText;
};
let unmarshalBody = '';
unmarshalBody = '\tfor key, val := range rawMsg {\n';
unmarshalBody += '\t\tvar err error\n';
unmarshalBody += '\t\tswitch key {\n';
let addlProps: go.MapType | undefined;
for (const field of values(modelType.fields)) {
if (go.isMapType(field.type) && field.annotations.isAdditionalProperties) {
addlProps = field.type;
continue;
}
unmarshalBody += `\t\tcase "${field.serializedName}":\n`;
if (hasDiscriminatorInterface(field.type)) {
unmarshalBody += generateDiscriminatorUnmarshaller(field, receiver);
} else if (go.isTimeType(field.type)) {
unmarshalBody += `\t\t\t\terr = unpopulate${capitalize(field.type.dateTimeFormat)}(val, "${field.name}", &${receiver}.${field.name})\n`;
modelDef.SerDe.needsJSONUnpopulate = true;
} else if (go.isSliceType(field.type) && go.isTimeType(field.type.elementType)) {
imports.add('time');
let elementPtr = '*';
if (field.type.elementTypeByValue) {
elementPtr = '';
}
unmarshalBody += `\t\t\tvar aux []${elementPtr}${field.type.elementType.dateTimeFormat}\n`;
unmarshalBody += `\t\t\terr = unpopulate(val, "${field.name}", &aux)\n`;
unmarshalBody += '\t\t\tfor _, au := range aux {\n';
unmarshalBody += `\t\t\t\t${receiver}.${field.name} = append(${receiver}.${field.name}, (${elementPtr}time.Time)(au))\n`;
unmarshalBody += '\t\t\t}\n';
modelDef.SerDe.needsJSONUnpopulate = true;
} else if (go.isBytesType(field.type)) {
imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime');
unmarshalBody += '\t\tif val != nil && string(val) != "null" {\n';
unmarshalBody += `\t\t\t\terr = runtime.DecodeByteArray(string(val), &${receiver}.${field.name}, runtime.Base64${field.type.encoding}Format)\n\t\t}\n`;
} else if (go.isSliceType(field.type) && go.isBytesType(field.type.elementType)) {
imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime');
unmarshalBody += '\t\t\tvar encodedValue []string\n';
unmarshalBody += `\t\t\terr = unpopulate(val, "${field.name}", &encodedValue)\n`;
unmarshalBody += '\t\t\tif err == nil && len(encodedValue) > 0 {\n';
unmarshalBody += `\t\t\t\t${receiver}.${field.name} = make([][]byte, len(encodedValue))\n`;
unmarshalBody += '\t\t\t\tfor i := 0; i < len(encodedValue) && err == nil; i++ {\n';
unmarshalBody += `\t\t\t\t\terr = runtime.DecodeByteArray(encodedValue[i], &${receiver}.${field.name}[i], runtime.Base64${field.type.elementType.encoding}Format)\n`;
unmarshalBody += '\t\t\t\t}\n\t\t\t}\n';
modelDef.SerDe.needsJSONUnpopulate = true;
} else if (go.isSliceType(field.type) && field.type.rawJSONAsBytes) {
unmarshalBody += '\t\t\tif string(val) != "null" {\n';
unmarshalBody += `\t\t\t\t${receiver}.${field.name} = val\n\t\t\t}\n`;
} else if (go.isPrimitiveType(field.type) && (field.type.typeName.startsWith('uint') || field.type.typeName.startsWith('int')) && field.type.encodeAsString) {
// TODO: need to handle map and slice type with underlying int as string type
imports.add('strconv');
unmarshalBody += `\t\t\t\tvar aux string\n`;
unmarshalBody += `\t\t\t\terr = unpopulate(val, "${field.name}", &aux)\n`;
unmarshalBody += `\t\t\t\tif err == nil {\n`;
unmarshalBody += `\t\t\t\t\tvar v ${field.type.typeName.startsWith('int') ? 'int64' : 'uint64'}\n`;
unmarshalBody += `\t\t\t\t\tv, err = strconv.${field.type.typeName.startsWith('int') ? 'ParseInt' : 'ParseUint'}(aux, 10, 0)\n`;
unmarshalBody += `\t\t\t\t\tif err == nil {\n`;
if (field.type.typeName.startsWith('uint') && field.type.typeName !== 'uint64' || field.type.typeName.startsWith('int') && field.type.typeName !== 'int64') {
unmarshalBody += `\t\t\t\t\t\t${receiver}.${field.name} = to.Ptr(${field.type.typeName}(v))\n`;
} else {
unmarshalBody += `\t\t\t\t\t\t${receiver}.${field.name} = to.Ptr(v)\n`;
}
unmarshalBody += '\t\t\t\t\t}\n';
unmarshalBody += '\t\t\t\t}\n';
modelDef.SerDe.needsJSONUnpopulate = true;
} else {
unmarshalBody += `\t\t\t\terr = unpopulate(val, "${field.name}", &${receiver}.${field.name})\n`;
modelDef.SerDe.needsJSONUnpopulate = true;
}
unmarshalBody += '\t\t\tdelete(rawMsg, key)\n';
}
if (addlProps) {
unmarshalBody += '\t\tdefault:\n';
unmarshalBody += emitAddlProps('\t', addlProps);
} else if (options.disallowUnknownFields) {
unmarshalBody += '\t\tdefault:\n';
unmarshalBody += `\t\t\terr = fmt.Errorf("unmarshalling type %T, unknown field %q", ${receiver}, key)\n`;
}
unmarshalBody += '\t\t}\n';
unmarshalBody += '\t\tif err != nil {\n';
unmarshalBody += `\t\t\treturn fmt.Errorf("unmarshalling type %T: %v", ${receiver}, err)\n`;
unmarshalBody += '\t\t}\n';
unmarshalBody += '\t}\n'; // end for key, val := range rawMsg
unmarshalBody += '\treturn nil\n';
return unmarshalBody;
}