Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Utf8JsonWriter to write JsonElement to stream instead of using th… #18436

Merged
merged 2 commits into from
Feb 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ internal async Task<ResponseWithHeaders<QueryResult<T>, QueryQueryTwinsHeaders>>
QuerySpecification querySpecification,
QueryOptions queryTwinsOptions = null,
ObjectSerializer objectSerializer = null,
ObjectSerializer defaultObjectSerializer = null,
CancellationToken cancellationToken = default)
{
if (querySpecification == null)
Expand All @@ -37,7 +36,7 @@ internal async Task<ResponseWithHeaders<QueryResult<T>, QueryQueryTwinsHeaders>>
case 200:
{
using JsonDocument document = await JsonDocument.ParseAsync(message.Response.ContentStream, default, cancellationToken).ConfigureAwait(false);
QueryResult<T> value = QueryResult<T>.DeserializeQueryResult(document.RootElement, objectSerializer, defaultObjectSerializer);
QueryResult<T> value = QueryResult<T>.DeserializeQueryResult(document.RootElement, objectSerializer);
return ResponseWithHeaders.FromValue(value, headers, message.Response);
}
default:
Expand All @@ -49,7 +48,6 @@ internal ResponseWithHeaders<QueryResult<T>, QueryQueryTwinsHeaders> QueryTwins<
QuerySpecification querySpecification,
QueryOptions queryTwinsOptions = null,
ObjectSerializer objectSerializer = null,
ObjectSerializer defaultObjectSerializer = null,
CancellationToken cancellationToken = default)
{
if (querySpecification == null)
Expand All @@ -70,7 +68,7 @@ internal ResponseWithHeaders<QueryResult<T>, QueryQueryTwinsHeaders> QueryTwins<
case 200:
{
using var document = JsonDocument.Parse(message.Response.ContentStream);
QueryResult<T> value = QueryResult<T>.DeserializeQueryResult(document.RootElement, objectSerializer, defaultObjectSerializer);
QueryResult<T> value = QueryResult<T>.DeserializeQueryResult(document.RootElement, objectSerializer);
return ResponseWithHeaders.FromValue(value, headers, message.Response);
}
default:
Expand Down
17 changes: 0 additions & 17 deletions sdk/digitaltwins/Azure.DigitalTwins.Core/src/DigitalTwinsClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,6 @@ public class DigitalTwinsClient

private readonly ObjectSerializer _objectSerializer;

/// <summary>
/// In order to serialize/deserialize JsonElements into and out of a stream, we have to use the out of the box ObjectSerializer (JsonObjectSerializer).
/// If the user specifies a different type of serializer to instantiate the client than the default one, the SDK will instantiate a new JsonObjectSerializer of its own.
/// </summary>
private readonly ObjectSerializer _defaultObjectSerializer;

private readonly DigitalTwinsRestClient _dtRestClient;
private readonly DigitalTwinModelsRestClient _dtModelsRestClient;
private readonly EventRoutesRestClient _eventRoutesRestClient;
Expand Down Expand Up @@ -99,13 +93,6 @@ public DigitalTwinsClient(Uri endpoint, TokenCredential credential, DigitalTwins

_objectSerializer = options.Serializer ?? new JsonObjectSerializer();

// If the objectSerializer is of type JsonObjectSerializer, we will re-use the same object and set it as the defaultObjectSerializer.
// Otherwise, we will instantiate it and re-use it in the future.
_defaultObjectSerializer =
(_objectSerializer is JsonObjectSerializer)
? _objectSerializer
: new JsonObjectSerializer();

options.AddPolicy(new BearerTokenAuthenticationPolicy(credential, GetAuthorizationScopes()), HttpPipelinePosition.PerCall);
_httpPipeline = HttpPipelineBuilder.Build(options);

Expand Down Expand Up @@ -2058,7 +2045,6 @@ async Task<Page<T>> FirstPageFunc(int? pageSizeHint)
querySpecification,
options,
_objectSerializer,
_defaultObjectSerializer,
cancellationToken)
.ConfigureAwait(false);

Expand Down Expand Up @@ -2093,7 +2079,6 @@ async Task<Page<T>> NextPageFunc(string nextLink, int? pageSizeHint)
querySpecification,
options,
_objectSerializer,
_defaultObjectSerializer,
cancellationToken)
.ConfigureAwait(false);

Expand Down Expand Up @@ -2169,7 +2154,6 @@ Page<T> FirstPageFunc(int? pageSizeHint)
querySpecification,
options,
_objectSerializer,
_defaultObjectSerializer,
cancellationToken);

return Page.FromValues(response.Value.Value, response.Value.ContinuationToken, response.GetRawResponse());
Expand Down Expand Up @@ -2203,7 +2187,6 @@ Page<T> NextPageFunc(string nextLink, int? pageSizeHint)
querySpecification,
options,
_objectSerializer,
_defaultObjectSerializer,
cancellationToken);

return Page.FromValues(response.Value.Value, response.Value.ContinuationToken, response.GetRawResponse());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,8 @@ internal QueryResult(IReadOnlyList<T> value, string continuationToken)
/// </summary>
/// <param name="element">The JSON element to be deserialized into a QueryResult.</param>
/// <param name="objectSerializer">The object serializer instance used to deserialize the items in the collection.</param>
/// <param name="defaultObjectSerializer">The out of the box object serializer to interact with the JsonElement (serialize/deserialize into and out of streams).</param>
/// <returns>A collection of query results deserialized into type <typeparamref name="T"/>.</returns>
internal static QueryResult<T> DeserializeQueryResult(JsonElement element, ObjectSerializer objectSerializer, ObjectSerializer defaultObjectSerializer)
internal static QueryResult<T> DeserializeQueryResult(JsonElement element, ObjectSerializer objectSerializer)
{
IReadOnlyList<T> items = default;
string continuationToken = default;
Expand All @@ -60,10 +59,7 @@ internal static QueryResult<T> DeserializeQueryResult(JsonElement element, Objec

foreach (JsonElement item in property.Value.EnumerateArray())
{
// defaultObjectSerializer of type JsonObjectSerializer needs to be used to serialize the JsonElement into a stream.
// Using any other ObjectSerializer (e.g. NewtonsoftJsonObjectSerializer) won't be able to deserialize the JsonElement into
// a MemoryStream correctly.
using MemoryStream streamedObject = StreamHelper.WriteToStream(item, defaultObjectSerializer, default);
using MemoryStream streamedObject = StreamHelper.WriteJsonElementToStream(item);

// To deserialize the stream object into the generic type of T, the provided ObjectSerializer will be used.
T obj = (T)objectSerializer.Deserialize(streamedObject, typeof(T), default);
Expand Down
18 changes: 18 additions & 0 deletions sdk/digitaltwins/Azure.DigitalTwins.Core/src/StreamHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT License.

using System.IO;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Azure.Core.Serialization;
Expand Down Expand Up @@ -46,5 +47,22 @@ internal static MemoryStream WriteToStream<T>(T obj, ObjectSerializer objectSeri

return memoryStream;
}

/// <summary>
/// Serializes a JsonElement and writes it into a memory stream.
/// </summary>
/// <param name="item">JsonElement to be deserialized into a stream.</param>
/// <returns>A binary representation of the object written to a stream.</returns>
internal static MemoryStream WriteJsonElementToStream(JsonElement item)
{
var memoryStream = new MemoryStream();
using var writer = new Utf8JsonWriter(memoryStream);

item.WriteTo(writer);
writer.Flush();
memoryStream.Seek(0, SeekOrigin.Begin);

return memoryStream;
}
}
}