Skip to content

Commit 9638ae4

Browse files
committed
Special-case JsonValue instances that wrap a JsonElement object
1 parent b0cacfe commit 9638ae4

File tree

3 files changed

+78
-82
lines changed

3 files changed

+78
-82
lines changed

shared/OpenIddict.Extensions/OpenIddictHelpers.cs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
using System.Security.Cryptography;
1414
using System.Text;
1515
using System.Text.Json;
16+
using System.Text.Json.Nodes;
1617
using Microsoft.Extensions.Primitives;
1718

1819
namespace OpenIddict.Extensions;
@@ -1066,6 +1067,61 @@ public static bool IsEcCurve(ECParameters parameters, ECCurve curve)
10661067
}
10671068
#endif
10681069

1070+
/// <summary>
1071+
/// Determines whether the specified <paramref name="element"/> represents a null, undefined or empty JSON node.
1072+
/// </summary>
1073+
/// <param name="element">The <see cref="JsonElement"/>.</param>
1074+
/// <returns>
1075+
/// <see langword="true"/> if the JSON node is null, undefined or empty <see langword="false"/> otherwise.
1076+
/// </returns>
1077+
public static bool IsNullOrEmpty(JsonElement element)
1078+
{
1079+
switch (element.ValueKind)
1080+
{
1081+
case JsonValueKind.Undefined or JsonValueKind.Null:
1082+
return true;
1083+
1084+
case JsonValueKind.String:
1085+
return string.IsNullOrEmpty(element.GetString());
1086+
1087+
case JsonValueKind.Array:
1088+
return element.GetArrayLength() is 0;
1089+
1090+
case JsonValueKind.Object:
1091+
#if SUPPORTS_JSON_ELEMENT_PROPERTY_COUNT
1092+
return element.GetPropertyCount() is 0;
1093+
#else
1094+
using (var enumerator = element.EnumerateObject())
1095+
{
1096+
return !enumerator.MoveNext();
1097+
}
1098+
#endif
1099+
default: return false;
1100+
}
1101+
}
1102+
1103+
/// <summary>
1104+
/// Determines whether the specified <paramref name="node"/> represents a null or empty JSON node.
1105+
/// </summary>
1106+
/// <param name="node">The <see cref="JsonNode"/>.</param>
1107+
/// <returns>
1108+
/// <see langword="true"/> if the JSON node is null or empty <see langword="false"/> otherwise.
1109+
/// </returns>
1110+
public static bool IsNullOrEmpty([NotNullWhen(false)] JsonNode? node) => node switch
1111+
{
1112+
null => true,
1113+
1114+
JsonArray value => value.Count is 0,
1115+
JsonObject value => value.Count is 0,
1116+
1117+
JsonValue value when value.TryGetValue(out string? result) => string.IsNullOrEmpty(result),
1118+
JsonValue value when value.TryGetValue(out JsonElement element) => IsNullOrEmpty(element),
1119+
1120+
// If the JSON node cannot be mapped to a primitive type, convert it to
1121+
// a JsonElement instance and infer the corresponding claim value type.
1122+
JsonNode value => IsNullOrEmpty(value.Deserialize(OpenIddictSerializer.Default.JsonElement))
1123+
};
1124+
10691125
/// <summary>
10701126
/// Determines whether the items contained in <paramref name="element"/>
10711127
/// are of the specified <paramref name="kind"/>.

src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs

Lines changed: 9 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
using System.Collections.Immutable;
88
using System.Diagnostics;
9-
using System.Diagnostics.CodeAnalysis;
109
using System.Globalization;
1110
using System.Runtime.CompilerServices;
1211
using System.Security.Claims;
@@ -15,6 +14,7 @@
1514
using System.Text.Json;
1615
using System.Text.Json.Nodes;
1716
using Microsoft.Extensions.Primitives;
17+
using OpenIddict.Extensions;
1818

1919
namespace OpenIddict.Abstractions;
2020

@@ -2261,7 +2261,7 @@ public static ClaimsIdentity SetClaim(this ClaimsIdentity identity, string type,
22612261

22622262
identity.RemoveClaims(type);
22632263

2264-
if (!IsEmptyJsonElement(value))
2264+
if (!OpenIddictHelpers.IsNullOrEmpty(value))
22652265
{
22662266
identity.AddClaim(type, value, issuer);
22672267
}
@@ -2291,7 +2291,7 @@ public static ClaimsPrincipal SetClaim(this ClaimsPrincipal principal, string ty
22912291

22922292
principal.RemoveClaims(type);
22932293

2294-
if (!IsEmptyJsonElement(value))
2294+
if (!OpenIddictHelpers.IsNullOrEmpty(value))
22952295
{
22962296
principal.AddClaim(type, value, issuer);
22972297
}
@@ -2341,7 +2341,7 @@ public static ClaimsIdentity SetClaim(this ClaimsIdentity identity, string type,
23412341

23422342
identity.RemoveClaims(type);
23432343

2344-
if (!IsEmptyJsonNode(value))
2344+
if (!OpenIddictHelpers.IsNullOrEmpty(value))
23452345
{
23462346
identity.AddClaim(type, value, issuer);
23472347
}
@@ -2371,7 +2371,7 @@ public static ClaimsPrincipal SetClaim(this ClaimsPrincipal principal, string ty
23712371

23722372
principal.RemoveClaims(type);
23732373

2374-
if (!IsEmptyJsonNode(value))
2374+
if (!OpenIddictHelpers.IsNullOrEmpty(value))
23752375
{
23762376
principal.AddClaim(type, value, issuer);
23772377
}
@@ -2591,7 +2591,7 @@ public static ClaimsIdentity SetClaims(this ClaimsIdentity identity, string type
25912591

25922592
identity.RemoveClaims(type);
25932593

2594-
if (!IsEmptyJsonElement(value))
2594+
if (!OpenIddictHelpers.IsNullOrEmpty(value))
25952595
{
25962596
identity.AddClaims(type, value, issuer);
25972597
}
@@ -2621,7 +2621,7 @@ public static ClaimsPrincipal SetClaims(this ClaimsPrincipal principal, string t
26212621

26222622
principal.RemoveClaims(type);
26232623

2624-
if (!IsEmptyJsonElement(value))
2624+
if (!OpenIddictHelpers.IsNullOrEmpty(value))
26252625
{
26262626
principal.AddClaims(type, value, issuer);
26272627
}
@@ -3932,6 +3932,8 @@ JsonValue value when value.TryGetValue<double>(out _) => ClaimValueTypes.Double
39323932
JsonArray => "JSON_ARRAY",
39333933
JsonObject => "JSON",
39343934

3935+
JsonValue value when value.TryGetValue(out JsonElement element) => GetClaimValueType(element),
3936+
39353937
// If the JSON node cannot be mapped to a primitive type, convert it to
39363938
// a JsonElement instance and infer the corresponding claim value type.
39373939
JsonNode value => GetClaimValueType(value.Deserialize(OpenIddictSerializer.Default.JsonElement))
@@ -3978,41 +3980,4 @@ JsonValue value when value.TryGetValue<double>(out _) => ClaimValueTypes.Double
39783980

39793981
return null;
39803982
}
3981-
3982-
private static bool IsEmptyJsonElement(JsonElement element)
3983-
{
3984-
switch (element.ValueKind)
3985-
{
3986-
case JsonValueKind.Undefined or JsonValueKind.Null:
3987-
return true;
3988-
3989-
case JsonValueKind.String:
3990-
return string.IsNullOrEmpty(element.GetString());
3991-
3992-
case JsonValueKind.Array:
3993-
return element.GetArrayLength() is 0;
3994-
3995-
case JsonValueKind.Object:
3996-
using (var enumerator = element.EnumerateObject())
3997-
{
3998-
return !enumerator.MoveNext();
3999-
}
4000-
4001-
default: return false;
4002-
}
4003-
}
4004-
4005-
private static bool IsEmptyJsonNode([NotNullWhen(false)] JsonNode? node) => node switch
4006-
{
4007-
null => true,
4008-
4009-
JsonArray value => value.Count is 0,
4010-
JsonObject value => value.Count is 0,
4011-
4012-
JsonValue value when value.TryGetValue(out string? result) => string.IsNullOrEmpty(result),
4013-
4014-
// If the JSON node cannot be mapped to a primitive type, convert it to
4015-
// a JsonElement instance and infer the corresponding claim value type.
4016-
JsonNode value => IsEmptyJsonElement(value.Deserialize(OpenIddictSerializer.Default.JsonElement))
4017-
};
40183983
}

src/OpenIddict.Abstractions/Primitives/OpenIddictParameter.cs

Lines changed: 13 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using System.Text.Json;
1313
using System.Text.Json.Nodes;
1414
using Microsoft.Extensions.Primitives;
15+
using OpenIddict.Extensions;
1516

1617
namespace OpenIddict.Abstractions;
1718

@@ -634,14 +635,13 @@ static IReadOnlyList<OpenIddictParameter> GetParametersFromJsonNode(JsonArray no
634635

635636
JsonElement value => value.ToString(),
636637

637-
JsonValue value when value.TryGetValue(out JsonElement element)
638-
=> element.ValueKind switch
639-
{
640-
JsonValueKind.True => "true",
641-
JsonValueKind.False => "false",
638+
JsonValue value when value.TryGetValue(out JsonElement element) => element.ValueKind switch
639+
{
640+
JsonValueKind.True => "true",
641+
JsonValueKind.False => "false",
642642

643-
_ => element.ToString()
644-
},
643+
_ => element.ToString()
644+
},
645645

646646
JsonValue value when value.TryGetValue(out bool result)
647647
=> result ? "true" : "false",
@@ -1310,8 +1310,7 @@ JsonValue value when value.TryGetValue(out JsonElement element) => ConvertFromJs
13101310
JsonValue value when value.TryGetValue(out string? result) => [result],
13111311

13121312
// When the parameter is a JsonValue wrapping a boolean, return an array with its string representation.
1313-
JsonValue value when value.TryGetValue(out bool result)
1314-
=> [result ? "true" : "false"],
1313+
JsonValue value when value.TryGetValue(out bool result) => [result ? "true" : "false"],
13151314

13161315
// When the parameter is a JsonValue wrapping an integer, return an array with its string representation.
13171316
JsonValue value when value.TryGetValue(out int result)
@@ -1483,45 +1482,21 @@ public static bool IsNullOrEmpty(OpenIddictParameter parameter)
14831482
string value => value.Length is 0,
14841483
string?[] value => value.Length is 0,
14851484

1486-
JsonElement value => IsEmptyJsonElement(value),
1485+
JsonElement value => OpenIddictHelpers.IsNullOrEmpty(value),
14871486

14881487
JsonArray value => value.Count is 0,
14891488
JsonObject value => value.Count is 0,
14901489

1491-
JsonValue value when value.TryGetValue(out JsonElement element)
1492-
=> IsEmptyJsonElement(element),
1490+
JsonValue value when value.TryGetValue(out string? result) => string.IsNullOrEmpty(result),
14931491

1494-
JsonValue value when value.TryGetValue(out string? result)
1495-
=> string.IsNullOrEmpty(result),
1492+
JsonValue value when value.TryGetValue(out JsonElement element)
1493+
=> OpenIddictHelpers.IsNullOrEmpty(element),
14961494

14971495
JsonNode value when JsonSerializer.SerializeToElement(value,
14981496
OpenIddictSerializer.Default.JsonNode) is JsonElement element
1499-
=> IsEmptyJsonElement(element),
1497+
=> OpenIddictHelpers.IsNullOrEmpty(element),
15001498

15011499
_ => false
15021500
};
1503-
1504-
static bool IsEmptyJsonElement(JsonElement element)
1505-
{
1506-
switch (element.ValueKind)
1507-
{
1508-
case JsonValueKind.String:
1509-
return string.IsNullOrEmpty(element.GetString());
1510-
1511-
case JsonValueKind.Array:
1512-
return element.GetArrayLength() is 0;
1513-
1514-
case JsonValueKind.Object:
1515-
#if SUPPORTS_JSON_ELEMENT_PROPERTY_COUNT
1516-
return element.GetPropertyCount() is 0;
1517-
#else
1518-
using (var enumerator = element.EnumerateObject())
1519-
{
1520-
return !enumerator.MoveNext();
1521-
}
1522-
#endif
1523-
default: return false;
1524-
}
1525-
}
15261501
}
15271502
}

0 commit comments

Comments
 (0)