From a94bd550d9bf509b1c48221f35780e4477b8eaff Mon Sep 17 00:00:00 2001 From: Anne Thompson Date: Mon, 22 Apr 2024 16:12:18 -0700 Subject: [PATCH 1/3] Add JsonModel --- .../api/System.ClientModel.net6.0.cs | 20 +++ .../api/System.ClientModel.netstandard2.0.cs | 20 +++ .../src/ModelReaderWriter/IJsonModel.cs | 31 +--- .../src/ModelReaderWriter/IJsonModelOfT.cs | 34 ++++ ...stableModel.cs => IPersistableModelOfT.cs} | 0 .../src/ModelReaderWriter/JsonModelOfT.cs | 163 ++++++++++++++++++ 6 files changed, 242 insertions(+), 26 deletions(-) create mode 100644 sdk/core/System.ClientModel/src/ModelReaderWriter/IJsonModelOfT.cs rename sdk/core/System.ClientModel/src/ModelReaderWriter/{IPersistableModel.cs => IPersistableModelOfT.cs} (100%) create mode 100644 sdk/core/System.ClientModel/src/ModelReaderWriter/JsonModelOfT.cs diff --git a/sdk/core/System.ClientModel/api/System.ClientModel.net6.0.cs b/sdk/core/System.ClientModel/api/System.ClientModel.net6.0.cs index 3edacd35c1d4..2a916a7a32cf 100644 --- a/sdk/core/System.ClientModel/api/System.ClientModel.net6.0.cs +++ b/sdk/core/System.ClientModel/api/System.ClientModel.net6.0.cs @@ -107,6 +107,10 @@ protected virtual void OnSendingRequest(System.ClientModel.Primitives.PipelineMe protected sealed override void ProcessCore(System.ClientModel.Primitives.PipelineMessage message) { } protected sealed override System.Threading.Tasks.ValueTask ProcessCoreAsync(System.ClientModel.Primitives.PipelineMessage message) { throw null; } } + public partial interface IJsonModel + { + System.Collections.Generic.Dictionary AdditionalProperties { get; } + } public partial interface IJsonModel : System.ClientModel.Primitives.IPersistableModel { T Create(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options); @@ -118,6 +122,22 @@ public partial interface IPersistableModel string GetFormatFromOptions(System.ClientModel.Primitives.ModelReaderWriterOptions options); System.BinaryData Write(System.ClientModel.Primitives.ModelReaderWriterOptions options); } + public abstract partial class JsonModel : System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IPersistableModel + { + protected JsonModel() { } + public string? AdditionalProperties { get { throw null; } set { } } + System.Collections.Generic.Dictionary System.ClientModel.Primitives.IJsonModel.AdditionalProperties { get { throw null; } } + protected abstract T CreateCore(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options); + protected virtual string GetFormatFromOptionsCore(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + protected void ReadUnknownProperty(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } + T System.ClientModel.Primitives.IJsonModel.Create(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + void System.ClientModel.Primitives.IJsonModel.Write(System.Text.Json.Utf8JsonWriter writer, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } + T System.ClientModel.Primitives.IPersistableModel.Create(System.BinaryData data, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + string System.ClientModel.Primitives.IPersistableModel.GetFormatFromOptions(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + System.BinaryData System.ClientModel.Primitives.IPersistableModel.Write(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + protected abstract void WriteCore(System.Text.Json.Utf8JsonWriter writer, System.ClientModel.Primitives.ModelReaderWriterOptions options); + protected void WriteUnknownProperties(System.Text.Json.Utf8JsonWriter writer, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } + } public static partial class ModelReaderWriter { public static object? Read(System.BinaryData data, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type returnType, System.ClientModel.Primitives.ModelReaderWriterOptions? options = null) { throw null; } diff --git a/sdk/core/System.ClientModel/api/System.ClientModel.netstandard2.0.cs b/sdk/core/System.ClientModel/api/System.ClientModel.netstandard2.0.cs index 2367ba7f518d..982d6ab60a4b 100644 --- a/sdk/core/System.ClientModel/api/System.ClientModel.netstandard2.0.cs +++ b/sdk/core/System.ClientModel/api/System.ClientModel.netstandard2.0.cs @@ -107,6 +107,10 @@ protected virtual void OnSendingRequest(System.ClientModel.Primitives.PipelineMe protected sealed override void ProcessCore(System.ClientModel.Primitives.PipelineMessage message) { } protected sealed override System.Threading.Tasks.ValueTask ProcessCoreAsync(System.ClientModel.Primitives.PipelineMessage message) { throw null; } } + public partial interface IJsonModel + { + System.Collections.Generic.Dictionary AdditionalProperties { get; } + } public partial interface IJsonModel : System.ClientModel.Primitives.IPersistableModel { T Create(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options); @@ -118,6 +122,22 @@ public partial interface IPersistableModel string GetFormatFromOptions(System.ClientModel.Primitives.ModelReaderWriterOptions options); System.BinaryData Write(System.ClientModel.Primitives.ModelReaderWriterOptions options); } + public abstract partial class JsonModel : System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IPersistableModel + { + protected JsonModel() { } + public string? AdditionalProperties { get { throw null; } set { } } + System.Collections.Generic.Dictionary System.ClientModel.Primitives.IJsonModel.AdditionalProperties { get { throw null; } } + protected abstract T CreateCore(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options); + protected virtual string GetFormatFromOptionsCore(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + protected void ReadUnknownProperty(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } + T System.ClientModel.Primitives.IJsonModel.Create(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + void System.ClientModel.Primitives.IJsonModel.Write(System.Text.Json.Utf8JsonWriter writer, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } + T System.ClientModel.Primitives.IPersistableModel.Create(System.BinaryData data, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + string System.ClientModel.Primitives.IPersistableModel.GetFormatFromOptions(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + System.BinaryData System.ClientModel.Primitives.IPersistableModel.Write(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + protected abstract void WriteCore(System.Text.Json.Utf8JsonWriter writer, System.ClientModel.Primitives.ModelReaderWriterOptions options); + protected void WriteUnknownProperties(System.Text.Json.Utf8JsonWriter writer, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } + } public static partial class ModelReaderWriter { public static object? Read(System.BinaryData data, System.Type returnType, System.ClientModel.Primitives.ModelReaderWriterOptions? options = null) { throw null; } diff --git a/sdk/core/System.ClientModel/src/ModelReaderWriter/IJsonModel.cs b/sdk/core/System.ClientModel/src/ModelReaderWriter/IJsonModel.cs index 0fc498a4da62..1f0cae85b0d8 100644 --- a/sdk/core/System.ClientModel/src/ModelReaderWriter/IJsonModel.cs +++ b/sdk/core/System.ClientModel/src/ModelReaderWriter/IJsonModel.cs @@ -1,34 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using System.Text.Json; +using System.Collections.Generic; namespace System.ClientModel.Primitives; -/// -/// Allows an object to control its own JSON writing and reading. -/// -/// The type the model can be converted into. -public interface IJsonModel : IPersistableModel +#pragma warning disable CS1591 // public XML comments +public interface IJsonModel { - /// - /// Writes the model to the provided . - /// - /// The to write into. - /// The to use. - /// If the model does not support the requested . -#pragma warning disable AZC0014 // Avoid using banned types in public API - void Write(Utf8JsonWriter writer, ModelReaderWriterOptions options); -#pragma warning restore AZC0014 // Avoid using banned types in public API - - /// - /// Reads one JSON value (including objects or arrays) from the provided reader and converts it to a model. - /// - /// The to read. - /// The to use. - /// A representation of the JSON value. - /// If the model does not support the requested . -#pragma warning disable AZC0014 // Avoid using banned types in public API - T Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options); -#pragma warning restore AZC0014 // Avoid using banned types in public API + Dictionary AdditionalProperties { get; } } +#pragma warning restore CS1591 // public XML comments diff --git a/sdk/core/System.ClientModel/src/ModelReaderWriter/IJsonModelOfT.cs b/sdk/core/System.ClientModel/src/ModelReaderWriter/IJsonModelOfT.cs new file mode 100644 index 000000000000..0fc498a4da62 --- /dev/null +++ b/sdk/core/System.ClientModel/src/ModelReaderWriter/IJsonModelOfT.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Text.Json; + +namespace System.ClientModel.Primitives; + +/// +/// Allows an object to control its own JSON writing and reading. +/// +/// The type the model can be converted into. +public interface IJsonModel : IPersistableModel +{ + /// + /// Writes the model to the provided . + /// + /// The to write into. + /// The to use. + /// If the model does not support the requested . +#pragma warning disable AZC0014 // Avoid using banned types in public API + void Write(Utf8JsonWriter writer, ModelReaderWriterOptions options); +#pragma warning restore AZC0014 // Avoid using banned types in public API + + /// + /// Reads one JSON value (including objects or arrays) from the provided reader and converts it to a model. + /// + /// The to read. + /// The to use. + /// A representation of the JSON value. + /// If the model does not support the requested . +#pragma warning disable AZC0014 // Avoid using banned types in public API + T Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options); +#pragma warning restore AZC0014 // Avoid using banned types in public API +} diff --git a/sdk/core/System.ClientModel/src/ModelReaderWriter/IPersistableModel.cs b/sdk/core/System.ClientModel/src/ModelReaderWriter/IPersistableModelOfT.cs similarity index 100% rename from sdk/core/System.ClientModel/src/ModelReaderWriter/IPersistableModel.cs rename to sdk/core/System.ClientModel/src/ModelReaderWriter/IPersistableModelOfT.cs diff --git a/sdk/core/System.ClientModel/src/ModelReaderWriter/JsonModelOfT.cs b/sdk/core/System.ClientModel/src/ModelReaderWriter/JsonModelOfT.cs new file mode 100644 index 000000000000..a54048f8bca2 --- /dev/null +++ b/sdk/core/System.ClientModel/src/ModelReaderWriter/JsonModelOfT.cs @@ -0,0 +1,163 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.IO; +using System.Text.Json; + +namespace System.ClientModel.Primitives; + +#pragma warning disable CS1591 // public XML comments +public abstract class JsonModel : IJsonModel, IJsonModel +{ + private Dictionary? _unknownProperties; + + Dictionary IJsonModel.AdditionalProperties + => _unknownProperties ??= new(); + +#pragma warning disable AZC0014 // Avoid using banned types in public API + protected abstract T CreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options); + + protected abstract void WriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options); +#pragma warning restore AZC0014 // Avoid using banned types in public API + + T IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + => CreateCore(ref reader, options); + + T IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var pm = this as IJsonModel; + var reader = new Utf8JsonReader(data); + return pm.Create(ref reader, options); + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) + => GetFormatFromOptionsCore(options); + + protected virtual string GetFormatFromOptionsCore(ModelReaderWriterOptions options) + { + if (options.Format == "W") + return "J"; + + throw new NotSupportedException(); + } + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + => WriteCore(writer, options); + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + using var stream = new MemoryStream(); + using var writer = new Utf8JsonWriter(stream); + + var jsonModel = this as IJsonModel; + jsonModel.Write(writer, options); + stream.Position = 0; + // TODO: flush? + + return BinaryData.FromStream(stream); + } + + private static BinaryData ReadUnknownValue(ref Utf8JsonReader reader) + { + var stream = new MemoryStream(); + int depth = 0; +#if NET6_0_OR_GREATER + bool writeComma = false; +#endif + + // TODO: netstandard2.0 + + while (true) + { + if (!reader.Read()) + throw new Exception(); + + switch (reader.TokenType) + { + case JsonTokenType.String: + if (depth == 0) + { + return new BinaryData(reader.ValueSpan.ToArray()); + } +#if NET6_0_OR_GREATER + stream.Write("\""u8); + stream.Write(reader.ValueSpan); + stream.Write("\""u8); + writeComma = true; +#endif + break; + case JsonTokenType.Number: + if (depth == 0) + { + return new BinaryData(reader.ValueSpan.ToArray()); + } +#if NET6_0_OR_GREATER + stream.Write(reader.ValueSpan); + writeComma = true; +#endif + break; + case JsonTokenType.EndObject: + case JsonTokenType.EndArray: +#if NET6_0_OR_GREATER + stream.Write(reader.ValueSpan); +#endif + depth--; + if (depth == 0) + { + stream.Position = 0; + return BinaryData.FromStream(stream); + } + break; + case JsonTokenType.StartObject: + case JsonTokenType.StartArray: + depth++; +#if NET6_0_OR_GREATER + stream.Write(reader.ValueSpan); +#endif + break; + case JsonTokenType.PropertyName: +#if NET6_0_OR_GREATER + if (writeComma) + { + stream.Write(",\n"u8); + writeComma = false; + } + stream.Write("\""u8); + stream.Write(reader.ValueSpan); + stream.Write("\":"u8); +#endif + break; + + default: + throw new NotImplementedException(); + } + } + } + +#pragma warning disable AZC0014 // Avoid using banned types in public API + protected void ReadUnknownProperty(ref Utf8JsonReader reader, ModelReaderWriterOptions options) +#pragma warning restore AZC0014 // Avoid using banned types in public API + { + string name = reader.GetString()!; + BinaryData value = ReadUnknownValue(ref reader); + ((IJsonModel)this).AdditionalProperties.Add(name, value); + } + +#pragma warning disable AZC0014 // Avoid using banned types in public API + protected void WriteUnknownProperties(Utf8JsonWriter writer, ModelReaderWriterOptions options) +#pragma warning restore AZC0014 // Avoid using banned types in public API + { + if (_unknownProperties != null) + { + foreach (var property in _unknownProperties) + { + writer.WritePropertyName(property.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(property.Value); +#endif + } + } + } +} +#pragma warning restore CS1591 // public XML comments From fe441fbec6ac6126154e27f94d96c8f8630cbd86 Mon Sep 17 00:00:00 2001 From: Anne Thompson Date: Mon, 22 Apr 2024 16:30:14 -0700 Subject: [PATCH 2/3] change to dictionary of object --- .../api/System.ClientModel.net6.0.cs | 5 ++--- .../api/System.ClientModel.netstandard2.0.cs | 5 ++--- .../src/ModelReaderWriter/IJsonModel.cs | 2 +- .../src/ModelReaderWriter/JsonModelOfT.cs | 11 ++++++++--- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/sdk/core/System.ClientModel/api/System.ClientModel.net6.0.cs b/sdk/core/System.ClientModel/api/System.ClientModel.net6.0.cs index 2a916a7a32cf..b40da1d0b88b 100644 --- a/sdk/core/System.ClientModel/api/System.ClientModel.net6.0.cs +++ b/sdk/core/System.ClientModel/api/System.ClientModel.net6.0.cs @@ -109,7 +109,7 @@ protected sealed override void ProcessCore(System.ClientModel.Primitives.Pipelin } public partial interface IJsonModel { - System.Collections.Generic.Dictionary AdditionalProperties { get; } + System.Collections.Generic.Dictionary AdditionalProperties { get; } } public partial interface IJsonModel : System.ClientModel.Primitives.IPersistableModel { @@ -125,8 +125,7 @@ public partial interface IPersistableModel public abstract partial class JsonModel : System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IPersistableModel { protected JsonModel() { } - public string? AdditionalProperties { get { throw null; } set { } } - System.Collections.Generic.Dictionary System.ClientModel.Primitives.IJsonModel.AdditionalProperties { get { throw null; } } + System.Collections.Generic.Dictionary System.ClientModel.Primitives.IJsonModel.AdditionalProperties { get { throw null; } } protected abstract T CreateCore(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options); protected virtual string GetFormatFromOptionsCore(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } protected void ReadUnknownProperty(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } diff --git a/sdk/core/System.ClientModel/api/System.ClientModel.netstandard2.0.cs b/sdk/core/System.ClientModel/api/System.ClientModel.netstandard2.0.cs index 982d6ab60a4b..9f95d97859fc 100644 --- a/sdk/core/System.ClientModel/api/System.ClientModel.netstandard2.0.cs +++ b/sdk/core/System.ClientModel/api/System.ClientModel.netstandard2.0.cs @@ -109,7 +109,7 @@ protected sealed override void ProcessCore(System.ClientModel.Primitives.Pipelin } public partial interface IJsonModel { - System.Collections.Generic.Dictionary AdditionalProperties { get; } + System.Collections.Generic.Dictionary AdditionalProperties { get; } } public partial interface IJsonModel : System.ClientModel.Primitives.IPersistableModel { @@ -125,8 +125,7 @@ public partial interface IPersistableModel public abstract partial class JsonModel : System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IPersistableModel { protected JsonModel() { } - public string? AdditionalProperties { get { throw null; } set { } } - System.Collections.Generic.Dictionary System.ClientModel.Primitives.IJsonModel.AdditionalProperties { get { throw null; } } + System.Collections.Generic.Dictionary System.ClientModel.Primitives.IJsonModel.AdditionalProperties { get { throw null; } } protected abstract T CreateCore(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options); protected virtual string GetFormatFromOptionsCore(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } protected void ReadUnknownProperty(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } diff --git a/sdk/core/System.ClientModel/src/ModelReaderWriter/IJsonModel.cs b/sdk/core/System.ClientModel/src/ModelReaderWriter/IJsonModel.cs index 1f0cae85b0d8..09459dac79d8 100644 --- a/sdk/core/System.ClientModel/src/ModelReaderWriter/IJsonModel.cs +++ b/sdk/core/System.ClientModel/src/ModelReaderWriter/IJsonModel.cs @@ -8,6 +8,6 @@ namespace System.ClientModel.Primitives; #pragma warning disable CS1591 // public XML comments public interface IJsonModel { - Dictionary AdditionalProperties { get; } + Dictionary AdditionalProperties { get; } } #pragma warning restore CS1591 // public XML comments diff --git a/sdk/core/System.ClientModel/src/ModelReaderWriter/JsonModelOfT.cs b/sdk/core/System.ClientModel/src/ModelReaderWriter/JsonModelOfT.cs index a54048f8bca2..f2b8133ef2fb 100644 --- a/sdk/core/System.ClientModel/src/ModelReaderWriter/JsonModelOfT.cs +++ b/sdk/core/System.ClientModel/src/ModelReaderWriter/JsonModelOfT.cs @@ -10,9 +10,9 @@ namespace System.ClientModel.Primitives; #pragma warning disable CS1591 // public XML comments public abstract class JsonModel : IJsonModel, IJsonModel { - private Dictionary? _unknownProperties; + private Dictionary? _unknownProperties; - Dictionary IJsonModel.AdditionalProperties + Dictionary IJsonModel.AdditionalProperties => _unknownProperties ??= new(); #pragma warning disable AZC0014 // Avoid using banned types in public API @@ -154,7 +154,12 @@ protected void WriteUnknownProperties(Utf8JsonWriter writer, ModelReaderWriterOp { writer.WritePropertyName(property.Key); #if NET6_0_OR_GREATER - writer.WriteRawValue(property.Value); + + // TODO: serialize or not as appropriate + // This is different depending on whether we decide on BinaryData + // dictionary or object dictionary. + + //writer.WriteRawValue(property.Value); #endif } } From 67eb84f24052b0882293cdd82cff4cf813f06aa5 Mon Sep 17 00:00:00 2001 From: Anne Thompson Date: Mon, 22 Apr 2024 18:08:16 -0700 Subject: [PATCH 3/3] updates --- .../api/System.ClientModel.net6.0.cs | 4 ++-- .../api/System.ClientModel.netstandard2.0.cs | 4 ++-- .../src/ModelReaderWriter/IJsonModel.cs | 2 +- .../src/ModelReaderWriter/JsonModelOfT.cs | 21 ++++++++++++------- 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/sdk/core/System.ClientModel/api/System.ClientModel.net6.0.cs b/sdk/core/System.ClientModel/api/System.ClientModel.net6.0.cs index b40da1d0b88b..ebb1d752e648 100644 --- a/sdk/core/System.ClientModel/api/System.ClientModel.net6.0.cs +++ b/sdk/core/System.ClientModel/api/System.ClientModel.net6.0.cs @@ -109,7 +109,7 @@ protected sealed override void ProcessCore(System.ClientModel.Primitives.Pipelin } public partial interface IJsonModel { - System.Collections.Generic.Dictionary AdditionalProperties { get; } + System.Collections.Generic.IDictionary AdditionalProperties { get; } } public partial interface IJsonModel : System.ClientModel.Primitives.IPersistableModel { @@ -125,7 +125,7 @@ public partial interface IPersistableModel public abstract partial class JsonModel : System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IPersistableModel { protected JsonModel() { } - System.Collections.Generic.Dictionary System.ClientModel.Primitives.IJsonModel.AdditionalProperties { get { throw null; } } + System.Collections.Generic.IDictionary System.ClientModel.Primitives.IJsonModel.AdditionalProperties { get { throw null; } } protected abstract T CreateCore(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options); protected virtual string GetFormatFromOptionsCore(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } protected void ReadUnknownProperty(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } diff --git a/sdk/core/System.ClientModel/api/System.ClientModel.netstandard2.0.cs b/sdk/core/System.ClientModel/api/System.ClientModel.netstandard2.0.cs index 9f95d97859fc..775f20d55344 100644 --- a/sdk/core/System.ClientModel/api/System.ClientModel.netstandard2.0.cs +++ b/sdk/core/System.ClientModel/api/System.ClientModel.netstandard2.0.cs @@ -109,7 +109,7 @@ protected sealed override void ProcessCore(System.ClientModel.Primitives.Pipelin } public partial interface IJsonModel { - System.Collections.Generic.Dictionary AdditionalProperties { get; } + System.Collections.Generic.IDictionary AdditionalProperties { get; } } public partial interface IJsonModel : System.ClientModel.Primitives.IPersistableModel { @@ -125,7 +125,7 @@ public partial interface IPersistableModel public abstract partial class JsonModel : System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IPersistableModel { protected JsonModel() { } - System.Collections.Generic.Dictionary System.ClientModel.Primitives.IJsonModel.AdditionalProperties { get { throw null; } } + System.Collections.Generic.IDictionary System.ClientModel.Primitives.IJsonModel.AdditionalProperties { get { throw null; } } protected abstract T CreateCore(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options); protected virtual string GetFormatFromOptionsCore(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } protected void ReadUnknownProperty(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } diff --git a/sdk/core/System.ClientModel/src/ModelReaderWriter/IJsonModel.cs b/sdk/core/System.ClientModel/src/ModelReaderWriter/IJsonModel.cs index 09459dac79d8..7c3237071a78 100644 --- a/sdk/core/System.ClientModel/src/ModelReaderWriter/IJsonModel.cs +++ b/sdk/core/System.ClientModel/src/ModelReaderWriter/IJsonModel.cs @@ -8,6 +8,6 @@ namespace System.ClientModel.Primitives; #pragma warning disable CS1591 // public XML comments public interface IJsonModel { - Dictionary AdditionalProperties { get; } + IDictionary AdditionalProperties { get; } } #pragma warning restore CS1591 // public XML comments diff --git a/sdk/core/System.ClientModel/src/ModelReaderWriter/JsonModelOfT.cs b/sdk/core/System.ClientModel/src/ModelReaderWriter/JsonModelOfT.cs index f2b8133ef2fb..2e3e663ece99 100644 --- a/sdk/core/System.ClientModel/src/ModelReaderWriter/JsonModelOfT.cs +++ b/sdk/core/System.ClientModel/src/ModelReaderWriter/JsonModelOfT.cs @@ -12,7 +12,7 @@ public abstract class JsonModel : IJsonModel, IJsonModel { private Dictionary? _unknownProperties; - Dictionary IJsonModel.AdditionalProperties + IDictionary IJsonModel.AdditionalProperties => _unknownProperties ??= new(); #pragma warning disable AZC0014 // Avoid using banned types in public API @@ -152,14 +152,21 @@ protected void WriteUnknownProperties(Utf8JsonWriter writer, ModelReaderWriterOp { foreach (var property in _unknownProperties) { + // Skip non-serialized items for now + // TODO: serialize non-serialized items in some cases? + if (property.Value is not BinaryData serializedValue) + { + continue; + } + writer.WritePropertyName(property.Key); #if NET6_0_OR_GREATER - - // TODO: serialize or not as appropriate - // This is different depending on whether we decide on BinaryData - // dictionary or object dictionary. - - //writer.WriteRawValue(property.Value); + writer.WriteRawValue(serializedValue); +#else + using (JsonDocument document = JsonDocument.Parse(serializedValue)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } #endif } }