Skip to content

Commit

Permalink
Add serializer support to JsonPatchDocument (#15754)
Browse files Browse the repository at this point in the history
Fixes: #15752
  • Loading branch information
pakrym authored Oct 7, 2020
1 parent cbb7115 commit dacf61d
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,16 @@ public void WriteTo(System.Text.Json.Utf8JsonWriter writer) { }
public partial class JsonPatchDocument
{
public JsonPatchDocument() { }
public void AppendAdd(string path, string rawJsonValue) { }
public JsonPatchDocument(Azure.Core.Serialization.ObjectSerializer serializer) { }
public void AppendAddRaw(string path, string rawJsonValue) { }
public void AppendAdd<T>(string path, T value, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { }
public void AppendCopy(string from, string path) { }
public void AppendMove(string from, string path) { }
public void AppendRemove(string path) { }
public void AppendReplace(string path, string rawJsonValue) { }
public void AppendTest(string path, string rawJsonValue) { }
public void AppendReplaceRaw(string path, string rawJsonValue) { }
public void AppendReplace<T>(string path, T value, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { }
public void AppendTestRaw(string path, string rawJsonValue) { }
public void AppendTest<T>(string path, T value, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { }
public override string ToString() { throw null; }
}
}
Expand Down
62 changes: 57 additions & 5 deletions sdk/core/Azure.Core.Experimental/src/JsonPatchDocument.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Text;
using System.Text.Json;
using System.Threading;
using Azure.Core.JsonPatch;
using Azure.Core.Serialization;

namespace Azure.Core
{
Expand All @@ -14,35 +17,66 @@ namespace Azure.Core
/// </summary>
public class JsonPatchDocument
{
internal Collection<JsonPatchOperation> Operations { get; }
private ObjectSerializer _serializer;
private Collection<JsonPatchOperation> Operations { get; }

/// <summary>
/// Initializes a new instance of <see cref="JsonPatchDocument"/> that uses <see cref="JsonObjectSerializer"/> as the default serializer.
/// </summary>
public JsonPatchDocument() : this(new JsonObjectSerializer())
{
}

/// <summary>
/// Initializes a new instance of <see cref="JsonPatchDocument"/>
/// </summary>
public JsonPatchDocument()
/// <param name="serializer">The <see cref="ObjectSerializer"/> instance to use for value serialization.</param>
public JsonPatchDocument(ObjectSerializer serializer)
{
Operations = new Collection<JsonPatchOperation>();
_serializer = serializer ?? throw new ArgumentNullException(nameof(serializer));
}

/// <summary>
/// Appends an "add" operation to this <see cref="JsonPatchDocument"/>.
/// </summary>
/// <param name="path">The path to apply the addition to.</param>
/// <param name="rawJsonValue">The raw JSON value to add to the path.</param>
public void AppendAdd(string path, string rawJsonValue)
public void AppendAddRaw(string path, string rawJsonValue)
{
Operations.Add(new JsonPatchOperation(JsonPatchOperationKind.Add, path, null, rawJsonValue));
}

/// <summary>
/// Appends an "add" operation to this <see cref="JsonPatchDocument"/>.
/// </summary>
/// <param name="path">The path to apply the addition to.</param>
/// <param name="value">The value to add to the path.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to use.</param>
public void AppendAdd<T>(string path, T value, CancellationToken cancellationToken = default)
{
Operations.Add(new JsonPatchOperation(JsonPatchOperationKind.Add, path, null, Serialize(value, cancellationToken)));
}

/// <summary>
/// Appends a "replace" operation to this <see cref="JsonPatchDocument"/>.
/// </summary>
/// <param name="path">The path to replace.</param>
/// <param name="rawJsonValue">The raw JSON value to replace with.</param>
public void AppendReplace(string path, string rawJsonValue)
public void AppendReplaceRaw(string path, string rawJsonValue)
{
Operations.Add(new JsonPatchOperation(JsonPatchOperationKind.Replace, path, null, rawJsonValue));
}
/// <summary>
/// Appends a "replace" operation to this <see cref="JsonPatchDocument"/>.
/// </summary>
/// <param name="path">The path to replace.</param>
/// <param name="value">The value to replace with.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to use.</param>
public void AppendReplace<T>(string path, T value, CancellationToken cancellationToken = default)
{
Operations.Add(new JsonPatchOperation(JsonPatchOperationKind.Replace, path, null, Serialize(value, cancellationToken)));
}

/// <summary>
/// Appends a "copy" operation to this <see cref="JsonPatchDocument"/>.
Expand Down Expand Up @@ -78,11 +112,22 @@ public void AppendRemove(string path)
/// </summary>
/// <param name="path">The path to test.</param>
/// <param name="rawJsonValue">The raw JSON value to test against.</param>
public void AppendTest(string path, string rawJsonValue)
public void AppendTestRaw(string path, string rawJsonValue)
{
Operations.Add(new JsonPatchOperation(JsonPatchOperationKind.Test, path, null, rawJsonValue));
}

/// <summary>
/// Appends a "test" operation to this <see cref="JsonPatchDocument"/>.
/// </summary>
/// <param name="path">The path to test.</param>
/// <param name="value">The value to replace with.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to use.</param>
public void AppendTest<T>(string path, T value, CancellationToken cancellationToken = default)
{
Operations.Add(new JsonPatchOperation(JsonPatchOperationKind.Test, path, null, Serialize(value, cancellationToken)));
}

/// <summary>
/// Returns a formatted JSON string representation of this <see cref="JsonPatchDocument"/>.
/// </summary>
Expand Down Expand Up @@ -119,5 +164,12 @@ private void WriteTo(Utf8JsonWriter writer)
}
writer.WriteEndArray();
}

private string Serialize<T>(T value, CancellationToken cancellationToken)
{
using MemoryStream memoryStream = new MemoryStream();
_serializer.Serialize(memoryStream, value, typeof(T), cancellationToken);
return Encoding.UTF8.GetString(memoryStream.ToArray());
}
}
}
36 changes: 30 additions & 6 deletions sdk/core/Azure.Core.Experimental/tests/JsonPatchDocumentTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,50 @@ public class JsonPatchDocumentTests
public void AddIsSerializedCorrectly()
{
JsonPatchDocument document = new JsonPatchDocument();
document.AppendAdd("/a/b/c","[ \"foo\", \"bar\" ]");
document.AppendAddRaw("/a/b/c","[ \"foo\", \"bar\" ]");
Assert.AreEqual(document.ToString(), "[{\"op\":\"add\",\"path\":\"/a/b/c\",\"value\":[\"foo\",\"bar\"]}]");
}

[Test]
public void AddIsSerializedCorrectlyGeneric()
{
JsonPatchDocument document = new JsonPatchDocument();
document.AppendAdd("/a/b/c",new[] { "foo", "bar" });
Assert.AreEqual(document.ToString(), "[{\"op\":\"add\",\"path\":\"/a/b/c\",\"value\":[\"foo\",\"bar\"]}]");
}

[Test]
public void ReplaceIsSerializedCorrectly()
{
JsonPatchDocument document = new JsonPatchDocument();
document.AppendReplace("/a/b/c","[ \"foo\", \"bar\" ]");
document.AppendReplaceRaw("/a/b/c","[ \"foo\", \"bar\" ]");
Assert.AreEqual(document.ToString(), "[{\"op\":\"replace\",\"path\":\"/a/b/c\",\"value\":[\"foo\",\"bar\"]}]");
}

[Test]
public void ReplaceIsSerializedCorrectlyGeneric()
{
JsonPatchDocument document = new JsonPatchDocument();
document.AppendReplace("/a/b/c",2);
Assert.AreEqual(document.ToString(), "[{\"op\":\"replace\",\"path\":\"/a/b/c\",\"value\":2}]");
}

[Test]
public void TestIsSerializedCorrectly()
{
JsonPatchDocument document = new JsonPatchDocument();
document.AppendTest("/a/b/c","[ \"foo\", \"bar\" ]");
document.AppendTestRaw("/a/b/c","[ \"foo\", \"bar\" ]");
Assert.AreEqual(document.ToString(), "[{\"op\":\"test\",\"path\":\"/a/b/c\",\"value\":[\"foo\",\"bar\"]}]");
}

[Test]
public void TestIsSerializedCorrectlyGeneric()
{
JsonPatchDocument document = new JsonPatchDocument();
document.AppendTest("/a/b/c",new { a = 2});
Assert.AreEqual(document.ToString(), "[{\"op\":\"test\",\"path\":\"/a/b/c\",\"value\":{\"a\":2}}]");
}

[Test]
public void RemoveIsSerializedCorrectly()
{
Expand Down Expand Up @@ -60,9 +84,9 @@ public void CopyIsSerializedCorrectly()
public void MultipleOperationsSerializedInOrder()
{
JsonPatchDocument document = new JsonPatchDocument();
document.AppendTest("/a/b/c","\"foo\"");
document.AppendAdd("/a/b/c","42");
document.AppendReplace("/a/b/c","[ \"foo\", \"bar\" ]");
document.AppendTestRaw("/a/b/c","\"foo\"");
document.AppendAddRaw("/a/b/c","42");
document.AppendReplaceRaw("/a/b/c","[ \"foo\", \"bar\" ]");
document.AppendRemove("/a/b/c");
document.AppendMove("/a/b/c", "/a/b/d");
document.AppendCopy("/a/b/c", "/a/b/d");
Expand Down

0 comments on commit dacf61d

Please sign in to comment.