azure-sdk-for-net
azure-sdk-for-net copied to clipboard
Core: PATCH | Support convenience layer and models for RFC7396 (application/merge-patch+json) operations
Scenario
For the following tsp spec
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 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
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);
}
}
Possible duplicate of https://github.com/Azure/azure-sdk-for-net/issues/27402