This repository is for active development of the Azure SDK for .NET. For consumers of the SDK we recommend visiting our public developer docs at https://learn.microsoft.com/dotnet/azure/ or our versioned developer docs at https://azure.github.io/azure-sdk-for-net.
MIT License
5.17k
stars
4.53k
forks
source link
Core: PATCH | Support convenience layer and models for RFC7396 (application/merge-patch+json) operations #42094
model PatchModel {
... // some properties
}
@patch
op patch(@header contentType: "application/merge-patch+json", @body body: PatchModel): PatchModel;
Currently we only provide protocol layer for operations with verb patch and don't generate models.
We are going to add
Convenience layer
Model and its corresponding serialization
to such patch operations with content type "application/merge-patch+json". For other patch operations not following RFC7396 is out of the scope.
Spec Interpretation
An input model in patch operation could also be in output model and other operations with different verbs. But we just generate the models defined in the spec, i.e. we don't generate special magic models for patch operation even when the model is in both patch operation and other operations.
An input model for patch operation could contain both required properties and optional properties:
a. Optional property property?: type should be taken as if it has | null, i.e. we could send null when serializing the explicitly optional property. If user defines property?: type| null, we should throw error.
b. Required property property: type should be taken as if it is property?: type, i.e. we could omit it over the wire, but it cannot be null.
c. For value of an optional array type property?: type[], its value is still not nullable, i.e. we cannot do model.Property[0] = null;
d. For value of an optional dictionary type property?: Record<type>, its value is nullable, i.e. we can do model.Property["a"] = null;
Convenience layer
The expected convenience layer for the above spec is like
public virtual async Task<PatchModel> PatchAsync(PatchModel body, CancellationToken cancellationToken = default)
{
using RequestContent content = RequestContent.Create(body, new ModelReaderWriterOptions("JMP"));
...
}
We are going to call above convert function to create RequestContent.
Serialization
We want to make sure we could do patch serialization not only from RequestContent.Create but also from IPersistableModel.Write. So the serialization code for model would be adjusted to
BinaryData IPersistableModel.Write(ModelReaderWriterOptions options)
{
var format = options.Format == "W" || options.Format == "JMP" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format;
switch (format)
{
case "J":
return ModelReaderWriter.Write(this, options);
default:
throw new FormatException($"The model {nameof(ResourcePatch)} does not support '{options.Format}' format.");
}
}
void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options)
{
var format = options.Format == "W" || options.Format == "JMP" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format;
if (format != "J")
{
throw new FormatException($"The model {nameof(ResourcePatch)} does not support '{format}' format.");
}
// maybe has other formats
if (options.Format == "W")
{
WriteJson(writer, options);
}
else if (options.Format == "JMP")
{
WritePatch(writer);
}
}
Scenario
For the following tsp spec
Currently we only provide protocol layer for operations with verb
patch
and don't generate models.We are going to add
to such patch operations with content type "application/merge-patch+json". For other patch operations not following RFC7396 is out of the scope.
Spec Interpretation
property?: type
should be taken as if it has| null
, i.e. we could sendnull
when serializing the explicitly optional property. If user definesproperty?: type| null
, we should throw error. b. Required propertyproperty: type
should be taken as if it isproperty?: type
, i.e. we could omit it over the wire, but it cannot benull
. c. For value of an optional array typeproperty?: type[]
, its value is still not nullable, i.e. we cannot domodel.Property[0] = null
; d. For value of an optional dictionary typeproperty?: Record<type>
, its value is nullable, i.e. we can domodel.Property["a"] = null
;Convenience layer
The expected convenience layer for the above spec is like
We are going to call above convert function to create
RequestContent
.Serialization
We want to make sure we could do patch serialization not only from
RequestContent.Create
but also fromIPersistableModel.Write
. So the serialization code for model would be adjusted to