Skip to content

Commit 1126f0b

Browse files
authored
[Low Level Client] Update to 3.1-preview.1 for service and add some convenience methods. (Azure#18885)
* [Core.Experimental] Tweak ToString() and add == overloads Today the `ToString` behavior of `JsonData` is "return a string which is the JSON encoding of the underlying object". This is reasonable but the implication is that `(new JsonData("foo")).ToString()` is `"foo"` (note the quotes) instead of just foo. This changes the behavior such that if the JsonData is an object or array we JSON serialize it, if it's null we return "<null>" and otherwise we just call .ToString() on the underlying value. The demo samples have been cleaned up as part of this change. * [Low Level Client] Updates - Implement Equals on JsonData to provide value equality semantics for primitive types. - Clean up debugger display of DynamicRequest/Response and JsonData - Move TA Client to 3.1-preview.1 of the API - Actually implement one of the user study tasks correctly by only reporting data for people (based on the result of another service call). - Implement user study task that flows data from one endpoint to another. * [Core.Experimental] Add Some JsonData Equals Tests
1 parent f48c411 commit 1126f0b

File tree

10 files changed

+656
-97
lines changed

10 files changed

+656
-97
lines changed

sdk/core/Azure.Core.Experimental/api/Azure.Core.Experimental.netstandard2.0.cs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public override void Dispose() { }
1010
public override void WriteTo(System.IO.Stream stream, System.Threading.CancellationToken cancellation) { }
1111
public override System.Threading.Tasks.Task WriteToAsync(System.IO.Stream stream, System.Threading.CancellationToken cancellation) { throw null; }
1212
}
13-
[System.Diagnostics.DebuggerDisplayAttribute("Body: {Body}")]
13+
[System.Diagnostics.DebuggerDisplayAttribute("{DebuggerDisplay,nq}")]
1414
public partial class DynamicRequest : Azure.Core.Request
1515
{
1616
public DynamicRequest(Azure.Core.Request request, Azure.Core.Pipeline.HttpPipeline pipeline) { }
@@ -29,7 +29,7 @@ protected virtual void Dispose(bool disposing) { }
2929
protected override bool TryGetHeader(string name, out string? value) { throw null; }
3030
protected override bool TryGetHeaderValues(string name, out System.Collections.Generic.IEnumerable<string>? values) { throw null; }
3131
}
32-
[System.Diagnostics.DebuggerDisplayAttribute("Status: {Response.Status}, Value: {Value}")]
32+
[System.Diagnostics.DebuggerDisplayAttribute("{DebuggerDisplay,nq}")]
3333
public partial class DynamicResponse : Azure.Response
3434
{
3535
public DynamicResponse(Azure.Response response, Azure.Core.JsonData? body) { }
@@ -47,7 +47,7 @@ protected virtual void Dispose(bool disposing) { }
4747
protected override bool TryGetHeaderValues(string name, out System.Collections.Generic.IEnumerable<string>? values) { throw null; }
4848
}
4949
[System.Diagnostics.DebuggerDisplayAttribute("{DebuggerDisplay,nq}")]
50-
public partial class JsonData : System.Dynamic.IDynamicMetaObjectProvider
50+
public partial class JsonData : System.Dynamic.IDynamicMetaObjectProvider, System.IEquatable<Azure.Core.JsonData>
5151
{
5252
public JsonData() { }
5353
public JsonData(object? value) { }
@@ -73,15 +73,20 @@ public void Add(string? value) { }
7373
public Azure.Core.JsonData Add<T>(T[] serializable, System.Text.Json.JsonSerializerOptions options) { throw null; }
7474
public static Azure.Core.JsonData EmptyArray() { throw null; }
7575
public static Azure.Core.JsonData EmptyObject() { throw null; }
76+
public bool Equals(Azure.Core.JsonData other) { throw null; }
77+
public override bool Equals(object? obj) { throw null; }
7678
public static Azure.Core.JsonData FromBytes(byte[] utf8Json) { throw null; }
7779
public static Azure.Core.JsonData FromBytes(System.ReadOnlyMemory<byte> utf8Json) { throw null; }
7880
public static Azure.Core.JsonData FromObject<T>(T value, System.Text.Json.JsonSerializerOptions? options = null) { throw null; }
7981
public static Azure.Core.JsonData FromStream(System.IO.Stream utf8Json) { throw null; }
8082
public static System.Threading.Tasks.Task<Azure.Core.JsonData> FromStreamAsync(System.IO.Stream utf8JsonStream, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
8183
public static Azure.Core.JsonData FromString(string json) { throw null; }
8284
public Azure.Core.JsonData? Get(string propertyName) { throw null; }
85+
public override int GetHashCode() { throw null; }
8386
public T Get<T>(string propertyName) { throw null; }
8487
public T Get<T>(string propertyName, System.Text.Json.JsonSerializerOptions options) { throw null; }
88+
public static bool operator ==(Azure.Core.JsonData? left, string? right) { throw null; }
89+
public static bool operator ==(string? left, Azure.Core.JsonData? right) { throw null; }
8590
public static explicit operator bool (Azure.Core.JsonData json) { throw null; }
8691
public static explicit operator double (Azure.Core.JsonData json) { throw null; }
8792
public static explicit operator int (Azure.Core.JsonData json) { throw null; }
@@ -104,6 +109,8 @@ public void Add(string? value) { }
104109
public static implicit operator Azure.Core.JsonData (float? value) { throw null; }
105110
public static implicit operator Azure.Core.JsonData (float value) { throw null; }
106111
public static implicit operator Azure.Core.JsonData (string? value) { throw null; }
112+
public static bool operator !=(Azure.Core.JsonData? left, string? right) { throw null; }
113+
public static bool operator !=(string? left, Azure.Core.JsonData? right) { throw null; }
107114
public void Set(string propertyName, bool value) { }
108115
public void Set(string propertyName, double value) { }
109116
public void Set(string propertyName, int value) { }
@@ -117,6 +124,7 @@ public void Set(string propertyName, string? value) { }
117124
public Azure.Core.JsonData Set<T>(string propertyName, T[] serializable) { throw null; }
118125
public Azure.Core.JsonData Set<T>(string propertyName, T[] serializable, System.Text.Json.JsonSerializerOptions options) { throw null; }
119126
System.Dynamic.DynamicMetaObject System.Dynamic.IDynamicMetaObjectProvider.GetMetaObject(System.Linq.Expressions.Expression parameter) { throw null; }
127+
public string ToJsonString() { throw null; }
120128
public override string ToString() { throw null; }
121129
public T To<T>() { throw null; }
122130
public T To<T>(System.Text.Json.JsonSerializerOptions options) { throw null; }

sdk/core/Azure.Core.Experimental/src/DynamicRequest.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ namespace Azure.Core
1818
/// <summary>
1919
/// Represents an HTTP request with <see cref="JsonData"/> content.
2020
/// </summary>
21-
[DebuggerDisplay("Body: {Body}")]
21+
[DebuggerDisplay("{DebuggerDisplay,nq}")]
2222
public class DynamicRequest : Request
2323
{
2424
private Request Request { get; }
@@ -153,5 +153,10 @@ protected virtual void Dispose(bool disposing)
153153

154154
/// <inheritdoc />
155155
protected override bool TryGetHeaderValues(string name, [NotNullWhen(true)] out IEnumerable<string>? values) => Request.Headers.TryGetValues(name, out values);
156+
157+
private string DebuggerDisplay
158+
{
159+
get => $"{{Body: {((Body == null) ? "" : Body.ToJsonString())}}}";
160+
}
156161
}
157162
}

sdk/core/Azure.Core.Experimental/src/DynamicResponse.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace Azure.Core
1313
/// <summary>
1414
/// Represents a result of Azure operation with a <see cref="JsonData"/> response.
1515
/// </summary>
16-
[DebuggerDisplay("Status: {Response.Status}, Value: {Value}")]
16+
[DebuggerDisplay("{DebuggerDisplay,nq}")]
1717
public class DynamicResponse : Response
1818
{
1919
private bool _disposed;
@@ -83,5 +83,10 @@ protected virtual void Dispose(bool disposing)
8383
}
8484
_disposed = true;
8585
}
86+
87+
private string DebuggerDisplay
88+
{
89+
get => $"{{Status: {Response.Status}, Body: {(Body == null ? "" : Body.ToJsonString())}}}";
90+
}
8691
}
8792
}

sdk/core/Azure.Core.Experimental/src/JsonData.cs

Lines changed: 130 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ namespace Azure.Core
2323
/// A mutable representation of a JSON value.
2424
/// </summary>
2525
[DebuggerDisplay("{DebuggerDisplay,nq}")]
26-
public class JsonData : IDynamicMetaObjectProvider
26+
public class JsonData : IDynamicMetaObjectProvider, IEquatable<JsonData>
2727
{
2828
private readonly JsonValueKind _kind;
2929
private Dictionary<string, JsonData>? _objectRepresentation;
@@ -35,7 +35,7 @@ public class JsonData : IDynamicMetaObjectProvider
3535
/// <summary>
3636
/// Creates a new JsonData object which represents an JSON object with no properties.
3737
/// </summary>
38-
public JsonData() : this(System.Array.Empty<KeyValuePair<string, JsonData>>())
38+
public JsonData() : this(Array.Empty<KeyValuePair<string, JsonData>>())
3939
{
4040
}
4141

@@ -242,8 +242,11 @@ public T To<T>(JsonSerializerOptions options)
242242
return JsonSerializer.Deserialize<T>(ToString(), options);
243243
}
244244

245-
/// <inheritdoc />
246-
public override string ToString()
245+
/// <summary>
246+
/// Returns a stringified version of the JSON for this value.
247+
/// </summary>
248+
/// <returns>Returns a stringified version of the JSON for this value.</returns>
249+
public string ToJsonString()
247250
{
248251
using var memoryStream = new MemoryStream();
249252
using (var writer = new Utf8JsonWriter(memoryStream))
@@ -725,6 +728,68 @@ public JsonData this[string propertyName]
725728
/// <param name="value">The value to convert.</param>
726729
public static implicit operator JsonData(bool? value) => new JsonData(value);
727730

731+
/// <summary>
732+
/// Returns true if a <see cref="JsonData"/> has the same value as a given string,
733+
/// and false otherwise.
734+
/// </summary>
735+
/// <param name="left">The <see cref="JsonData"/> to compare.</param>
736+
/// <param name="right">The <see cref="string"/> to compare.</param>
737+
/// <returns>True if the given JsonData represents the given string, and false otherwise.</returns>
738+
public static bool operator ==(JsonData? left, string? right)
739+
{
740+
if (left is null && right is null)
741+
{
742+
return true;
743+
}
744+
745+
if (left is null || right is null)
746+
{
747+
return false;
748+
}
749+
750+
return left.Kind == JsonValueKind.String && ((string?) left._value) == right;
751+
}
752+
753+
/// <summary>
754+
/// Returns false if a <see cref="JsonData"/> has the same value as a given string,
755+
/// and true otherwise.
756+
/// </summary>
757+
/// <param name="left">The <see cref="JsonData"/> to compare.</param>
758+
/// <param name="right">The <see cref="string"/> to compare.</param>
759+
/// <returns>False if the given JsonData represents the given string, and false otherwise</returns>
760+
public static bool operator !=(JsonData? left, string? right) => !(left == right);
761+
762+
/// <summary>
763+
/// Returns true if a <see cref="JsonData"/> has the same value as a given string,
764+
/// and false otherwise.
765+
/// </summary>
766+
/// <param name="left">The <see cref="string"/> to compare.</param>
767+
/// <param name="right">The <see cref="JsonData"/> to compare.</param>
768+
/// <returns>True if the given JsonData represents the given string, and false otherwise.</returns>
769+
public static bool operator ==(string? left, JsonData? right)
770+
{
771+
if (left is null && right is null)
772+
{
773+
return true;
774+
}
775+
776+
if (left is null || right is null)
777+
{
778+
return false;
779+
}
780+
781+
return right.Kind == JsonValueKind.String && ((string?)right._value) == left;
782+
}
783+
784+
/// <summary>
785+
/// Returns false if a <see cref="JsonData"/> has the same value as a given string,
786+
/// and true otherwise.
787+
/// </summary>
788+
/// <param name="left">The <see cref="string"/> to compare.</param>
789+
/// <param name="right">The <see cref="JsonData"/> to compare.</param>
790+
/// <returns>False if the given JsonData represents the given string, and false otherwise</returns>
791+
public static bool operator !=(string? left, JsonData? right) => !(left == right);
792+
728793
/// <summary>
729794
/// Parses text representing a single JSON value into a <see cref="JsonData"/>.
730795
/// </summary>
@@ -843,6 +908,66 @@ public async Task<long> WriteToAsync(Stream stream, CancellationToken cancellati
843908
return writer.BytesCommitted;
844909
}
845910

911+
/// <inheritdoc />
912+
public override string ToString()
913+
{
914+
if (_kind == JsonValueKind.Object || _kind == JsonValueKind.Array)
915+
{
916+
return ToJsonString();
917+
}
918+
919+
return (_value ?? "<null>").ToString();
920+
}
921+
922+
/// <inheritdoc />
923+
public override bool Equals(object? obj)
924+
{
925+
if (obj is string)
926+
{
927+
return this == ((string?)obj);
928+
}
929+
930+
if (obj is JsonData)
931+
{
932+
return Equals((JsonData)obj);
933+
}
934+
935+
return base.Equals(obj);
936+
}
937+
938+
/// <inheritdoc />
939+
public bool Equals(JsonData other)
940+
{
941+
if (_kind != other._kind)
942+
{
943+
return false;
944+
}
945+
946+
switch (_kind)
947+
{
948+
case JsonValueKind.Null:
949+
case JsonValueKind.Undefined:
950+
return true;
951+
case JsonValueKind.Object:
952+
return _objectRepresentation!.Equals(other._objectRepresentation);
953+
case JsonValueKind.Array:
954+
return _arrayRepresentation!.Equals(other._arrayRepresentation);
955+
default:
956+
return _value!.Equals(other._value);
957+
}
958+
}
959+
960+
/// <inheritdoc />
961+
public override int GetHashCode()
962+
{
963+
if (_kind == JsonValueKind.String)
964+
{
965+
return ((string?)_value)!.GetHashCode();
966+
}
967+
968+
return base.GetHashCode();
969+
}
970+
846971
private string? GetString() => (string?)EnsureValue();
847972
private int GetIn32()
848973
{
@@ -1017,7 +1142,7 @@ private IEnumerable GetDynamicEnumerable()
10171142

10181143
private string DebuggerDisplay
10191144
{
1020-
get => $"Kind: {_kind}, Value: {ToString()}";
1145+
get => $"{{Kind: {_kind}, JSON: {ToJsonString()}}}";
10211146
}
10221147

10231148
private struct Number

sdk/core/Azure.Core.Experimental/tests/JsonDataTests.cs

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public void CanCreateFromJson()
2424
{
2525
var jsonData = JsonData.FromString("\"string\"");
2626

27-
Assert.AreEqual("\"string\"", jsonData.ToString());
27+
Assert.AreEqual("\"string\"", jsonData.ToJsonString());
2828
}
2929

3030
[Test]
@@ -223,6 +223,61 @@ public void RoundtripObjects()
223223
Assert.AreEqual(model, roundtripped);
224224
}
225225

226+
[Test]
227+
public void EqualsProvidesValueEqualityPrimitives()
228+
{
229+
Assert.AreEqual(new JsonData(1), new JsonData(1));
230+
Assert.AreEqual(new JsonData(true), new JsonData(true));
231+
Assert.AreEqual(new JsonData(false), new JsonData(false));
232+
Assert.AreEqual(new JsonData("hello"), new JsonData("hello"));
233+
Assert.AreEqual(new JsonData(null), new JsonData(null));
234+
}
235+
236+
[Test]
237+
public void EqualsHandlesStringsSpecial()
238+
{
239+
Assert.IsTrue((new JsonData("test").Equals("test")));
240+
Assert.IsTrue((new JsonData("test").Equals(new JsonData("test"))));
241+
}
242+
243+
[Test]
244+
public void EqualsForObjectsAndArrays()
245+
{
246+
JsonData obj1 = new JsonData(new { foo = "bar" });
247+
JsonData obj2 = new JsonData(new { foo = "bar" });
248+
249+
JsonData arr1 = new JsonData(new[] { "bar" });
250+
JsonData arr2 = new JsonData(new[] { "bar" });
251+
252+
// For objects and arrays, Equals provides reference equality.
253+
Assert.AreEqual(obj1, obj1);
254+
Assert.AreEqual(arr1, arr1);
255+
256+
Assert.AreNotEqual(obj1, obj2);
257+
Assert.AreNotEqual(arr1, arr2);
258+
}
259+
260+
[Test]
261+
public void EqualsAndNull()
262+
{
263+
Assert.AreNotEqual(new JsonData(null), null);
264+
Assert.AreNotEqual(null, new JsonData(null));
265+
}
266+
267+
[Test]
268+
public void OperatorEqualsForString()
269+
{
270+
Assert.IsTrue(new JsonData("foo") == "foo");
271+
Assert.IsTrue("foo" == new JsonData("foo"));
272+
Assert.IsFalse(new JsonData("foo") != "foo");
273+
Assert.IsFalse("foo" != new JsonData("foo"));
274+
275+
Assert.IsFalse(new JsonData("bar") == "foo");
276+
Assert.IsFalse("foo" == new JsonData("bar"));
277+
Assert.IsTrue(new JsonData("bar") != "foo");
278+
Assert.IsTrue("foo" != new JsonData("bar"));
279+
}
280+
226281
private T JsonAsType<T>(string json)
227282
{
228283
dynamic jsonData = JsonData.FromString(json);

0 commit comments

Comments
 (0)