Skip to content

Commit 16a0706

Browse files
committed
Introduced new "GetRequiredType" extension methods for "JObject"
1 parent c13c296 commit 16a0706

16 files changed

+848
-1
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System;
2+
3+
namespace Skybrud.Essentials.Json.Newtonsoft.Exceptions;
4+
5+
/// <summary>
6+
/// Class representing an exception related to the JSON.net implementation.
7+
/// </summary>
8+
public class JsonException : Exception {
9+
10+
/// <summary>
11+
/// Initializes a new instance based on the specified <paramref name="message"/>.
12+
/// </summary>
13+
/// <param name="message">The exception message.</param>
14+
public JsonException(string message) : base(message) { }
15+
16+
/// <summary>
17+
/// Initializes a new instance based on the specified <paramref name="message"/> and <paramref name="innerException"/>.
18+
/// </summary>
19+
/// <param name="message">The exception message.</param>
20+
/// <param name="innerException">The inner exception, if any.</param>
21+
public JsonException(string message, Exception? innerException) : base(message, innerException) { }
22+
23+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using Newtonsoft.Json.Linq;
2+
3+
namespace Skybrud.Essentials.Json.Newtonsoft.Exceptions;
4+
5+
/// <summary>
6+
/// Exception thrown when a required JSON property was not found.
7+
/// </summary>
8+
public class JsonPropertyNotFoundException : JsonException {
9+
10+
/// <summary>
11+
/// Gets a reference to the JSON object.
12+
/// </summary>
13+
public new JObject Source { get; }
14+
15+
/// <summary>
16+
/// Gets the name of the property.
17+
/// </summary>
18+
public string PropertyName { get; }
19+
20+
/// <summary>
21+
/// Initializes a new exception based on the specified <paramref name="source"/> and <paramref name="propertyName"/>.
22+
/// </summary>
23+
/// <param name="source">A reference to the JSON object where the property was expected.</param>
24+
/// <param name="propertyName">The name of the property.</param>
25+
public JsonPropertyNotFoundException(JObject source, string propertyName) : base($"JSON property with name '{propertyName}' not found.") {
26+
Source = source;
27+
PropertyName = propertyName;
28+
}
29+
30+
/// <summary>
31+
/// Initializes a new exception based on the specified <paramref name="source"/> and <paramref name="propertyName"/>.
32+
/// </summary>
33+
/// <param name="source">A reference to the JSON object where the property was expected.</param>
34+
/// <param name="propertyName">The name of the property.</param>
35+
/// <param name="message">The exception message.</param>
36+
public JsonPropertyNotFoundException(JObject source, string propertyName, string message) : base(message) {
37+
Source = source;
38+
PropertyName = propertyName;
39+
}
40+
41+
}

src/Skybrud.Essentials/Json/Newtonsoft/Extensions/NewtonsoftJsonObjectExtensions.Boolean.cs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
using System.Diagnostics.CodeAnalysis;
1+
using System;
2+
using System.Diagnostics.CodeAnalysis;
23
using Newtonsoft.Json.Linq;
4+
using Skybrud.Essentials.Json.Newtonsoft.Exceptions;
35
using Skybrud.Essentials.Json.Newtonsoft.Parsing;
46

57
namespace Skybrud.Essentials.Json.Newtonsoft.Extensions;
@@ -124,4 +126,36 @@ public static bool TryGetBooleanByPath(this JObject? json, string path, [NotNull
124126
return JsonTokenUtils.TryGetBoolean(json?.SelectToken(path), out result);
125127
}
126128

129+
/// <summary>
130+
/// Returns the <see cref="bool"/> value of the property with the specified <paramref name="propertyName"/>. If a
131+
/// matching property isn't found, or the value doesn't match a valid <see cref="bool"/>, an exception is thrown
132+
/// instead.
133+
/// </summary>
134+
/// <param name="json">The parent JSON object.</param>
135+
/// <param name="propertyName">The name of the property.</param>
136+
/// <returns>The <see cref="bool"/> value.</returns>
137+
/// <exception cref="JsonPropertyNotFoundException">If a property matching <paramref name="propertyName"/> isn't found.</exception>
138+
/// <exception cref="JsonException">If the property is found, but the value doesn't match a <see cref="bool"/>.</exception>
139+
public static bool GetRequiredBoolean(this JObject json, string propertyName) {
140+
JProperty property = json.Property(propertyName) ?? throw new JsonPropertyNotFoundException(json, propertyName);
141+
if (!JsonTokenUtils.TryGetBoolean(property.Value, out bool result)) throw new JsonException($"The value of the '{propertyName}' property doesn't match a valid boolean value.");
142+
return result;
143+
}
144+
145+
/// <summary>
146+
/// Returns the value of the property with the specified <paramref name="propertyName"/>. If a matching property is
147+
/// found, the value is converted using <paramref name="callback"/>. If not found, an exception will be thrown instead.
148+
/// </summary>
149+
/// <param name="json">The parent JSON object.</param>
150+
/// <param name="propertyName">The name of the property.</param>
151+
/// <param name="callback">A callback function used for converting the <see cref="bool"/> value to <typeparamref name="TResult"/>.</param>
152+
/// <returns>The property value as an instance of <typeparamref name="TResult"/>.</returns>
153+
/// <exception cref="JsonPropertyNotFoundException">If a property matching <paramref name="propertyName"/> isn't found.</exception>
154+
/// <exception cref="JsonException">If the property is found, but the value doesn't match a <see cref="bool"/>.</exception>
155+
public static TResult GetRequiredBoolean<TResult>(this JObject json, string propertyName, Func<bool, TResult> callback) where TResult : notnull {
156+
JProperty property = json.Property(propertyName) ?? throw new JsonPropertyNotFoundException(json, propertyName);
157+
if (!JsonTokenUtils.TryGetBoolean(property.Value, out bool result)) throw new JsonException($"The value of the '{propertyName}' property doesn't match a valid boolean value.");
158+
return callback(result);
159+
}
160+
127161
}

src/Skybrud.Essentials/Json/Newtonsoft/Extensions/NewtonsoftJsonObjectExtensions.Double.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Diagnostics.CodeAnalysis;
33
using Newtonsoft.Json.Linq;
4+
using Skybrud.Essentials.Json.Newtonsoft.Exceptions;
45
using Skybrud.Essentials.Json.Newtonsoft.Parsing;
56

67
namespace Skybrud.Essentials.Json.Newtonsoft.Extensions;
@@ -174,4 +175,36 @@ public static double[] GetDoubleArrayByPath(this JObject? json, string path) {
174175
return JsonTokenUtils.GetDoubleArray(json?.SelectToken(path));
175176
}
176177

178+
/// <summary>
179+
/// Returns the <see cref="double"/> value of the property with the specified <paramref name="propertyName"/>. If a
180+
/// matching property isn't found, or the value doesn't match a valid <see cref="double"/>, an exception is thrown
181+
/// instead.
182+
/// </summary>
183+
/// <param name="json">The parent JSON object.</param>
184+
/// <param name="propertyName">The name of the property.</param>
185+
/// <returns>The <see cref="double"/> value.</returns>
186+
/// <exception cref="JsonPropertyNotFoundException">If a property matching <paramref name="propertyName"/> isn't found.</exception>
187+
/// <exception cref="JsonException">If the property is found, but the value doesn't match a <see cref="double"/>.</exception>
188+
public static double GetRequiredDouble(this JObject json, string propertyName) {
189+
JProperty property = json.Property(propertyName) ?? throw new JsonPropertyNotFoundException(json, propertyName);
190+
if (!JsonTokenUtils.TryGetDouble(property.Value, out double result)) throw new JsonException($"The value of the '{propertyName}' property doesn't match a valid double value.");
191+
return result;
192+
}
193+
194+
/// <summary>
195+
/// Returns the value of the property with the specified <paramref name="propertyName"/>. If a matching property is
196+
/// found, the value is converted using <paramref name="callback"/>. If not found, an exception will be thrown instead.
197+
/// </summary>
198+
/// <param name="json">The parent JSON object.</param>
199+
/// <param name="propertyName">The name of the property.</param>
200+
/// <param name="callback">A callback function used for converting the <see cref="double"/> value to <typeparamref name="TResult"/>.</param>
201+
/// <returns>The <see cref="double"/> value.</returns>
202+
/// <exception cref="JsonPropertyNotFoundException">If a property matching <paramref name="propertyName"/> isn't found.</exception>
203+
/// <exception cref="JsonException">If the property is found, but the value doesn't match a <see cref="double"/>.</exception>
204+
public static TResult GetRequiredDouble<TResult>(this JObject json, string propertyName, Func<double, TResult> callback) where TResult : notnull {
205+
JProperty property = json.Property(propertyName) ?? throw new JsonPropertyNotFoundException(json, propertyName);
206+
if (!JsonTokenUtils.TryGetDouble(property.Value, out double result)) throw new JsonException($"The value of the '{propertyName}' property doesn't match a valid double value.");
207+
return callback(result);
208+
}
209+
177210
}

src/Skybrud.Essentials/Json/Newtonsoft/Extensions/NewtonsoftJsonObjectExtensions.Enum.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using Newtonsoft.Json.Linq;
3+
using Skybrud.Essentials.Json.Newtonsoft.Exceptions;
34
using Skybrud.Essentials.Json.Newtonsoft.Parsing;
45

56
namespace Skybrud.Essentials.Json.Newtonsoft.Extensions;
@@ -63,4 +64,39 @@ public static T GetEnumByPath<T>(this JObject? json, string path, T fallback) wh
6364
return JsonTokenUtils.GetEnum(json?.SelectToken(path), fallback);
6465
}
6566

67+
/// <summary>
68+
/// Returns the enum value of the property with the specified <paramref name="propertyName"/>. If a matching
69+
/// property isn't found, or the value doesn't match a valid <typeparamref name="TEnum"/>, an exception is thrown
70+
/// instead.
71+
/// </summary>
72+
/// <typeparam name="TEnum">The type of the enum.</typeparam>
73+
/// <param name="json">The parent JSON object.</param>
74+
/// <param name="propertyName">The name of the property.</param>
75+
/// <returns>The enum value.</returns>
76+
/// <exception cref="JsonPropertyNotFoundException">If a property matching <paramref name="propertyName"/> isn't found.</exception>
77+
/// <exception cref="JsonException">If the property is found, but the value doesn't match a <see cref="double"/>.</exception>
78+
public static TEnum GetRequiredEnum<TEnum>(this JObject json, string propertyName) where TEnum : struct, Enum {
79+
JProperty property = json.Property(propertyName) ?? throw new JsonPropertyNotFoundException(json, propertyName);
80+
return JsonTokenUtils.GetEnumOrNull<TEnum>(property.Value) ?? throw new JsonException($"The value of the '{propertyName}' property doesn't match a value of enum '{typeof(Enum)}'.");
81+
}
82+
83+
/// <summary>
84+
/// Returns the value of the property with the specified <paramref name="propertyName"/>. If a matching property is
85+
/// found, the value is converted using <paramref name="callback"/>. If not found, or the value doesn't match a
86+
/// valid <typeparamref name="TEnum"/>, an exception will be thrown instead.
87+
/// </summary>
88+
/// <typeparam name="TEnum">The type of the enum.</typeparam>
89+
/// <typeparam name="TResult">The type of the result.</typeparam>
90+
/// <param name="json">The parent JSON object.</param>
91+
/// <param name="propertyName">The name of the property.</param>
92+
/// <param name="callback">A callback function used for converting the <see cref="double"/> value to <typeparamref name="TResult"/>.</param>
93+
/// <returns>The property value as an instance of <typeparamref name="TResult"/>.</returns>
94+
/// <exception cref="JsonPropertyNotFoundException">If a property matching <paramref name="propertyName"/> isn't found.</exception>
95+
/// <exception cref="JsonException">If the property is found, but the value doesn't match a <see cref="double"/>.</exception>
96+
public static TResult GetRequiredEnum<TEnum, TResult>(this JObject json, string propertyName, Func<TEnum, TResult> callback) where TEnum : struct, Enum {
97+
JProperty property = json.Property(propertyName) ?? throw new JsonPropertyNotFoundException(json, propertyName);
98+
if (JsonTokenUtils.GetEnumOrNull<TEnum>(property.Value) is not {} value) throw new JsonException($"The value of the '{propertyName}' property doesn't match a value of enum '{typeof(Enum)}'.");
99+
return callback(value);
100+
}
101+
66102
}

src/Skybrud.Essentials/Json/Newtonsoft/Extensions/NewtonsoftJsonObjectExtensions.Float.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Diagnostics.CodeAnalysis;
33
using Newtonsoft.Json.Linq;
4+
using Skybrud.Essentials.Json.Newtonsoft.Exceptions;
45
using Skybrud.Essentials.Json.Newtonsoft.Parsing;
56

67
namespace Skybrud.Essentials.Json.Newtonsoft.Extensions;
@@ -174,4 +175,36 @@ public static float[] GetFloatArrayByPath(this JObject? json, string path) {
174175
return JsonTokenUtils.GetFloatArray(json?.SelectToken(path));
175176
}
176177

178+
/// <summary>
179+
/// Returns the <see cref="float"/> value of the property with the specified <paramref name="propertyName"/>. If a
180+
/// matching property isn't found, or the value doesn't match a valid <see cref="float"/>, an exception is thrown
181+
/// instead.
182+
/// </summary>
183+
/// <param name="json">The parent JSON object.</param>
184+
/// <param name="propertyName">The name of the property.</param>
185+
/// <returns>The <see cref="float"/> value.</returns>
186+
/// <exception cref="JsonPropertyNotFoundException">If a property matching <paramref name="propertyName"/> isn't found.</exception>
187+
/// <exception cref="JsonException">If the property is found, but the value doesn't match a <see cref="float"/>.</exception>
188+
public static float GetRequiredFloat(this JObject json, string propertyName) {
189+
JProperty property = json.Property(propertyName) ?? throw new JsonPropertyNotFoundException(json, propertyName);
190+
if (!JsonTokenUtils.TryGetFloat(property.Value, out float result)) throw new JsonException($"The value of the '{propertyName}' property doesn't match a valid float value.");
191+
return result;
192+
}
193+
194+
/// <summary>
195+
/// Returns the value of the property with the specified <paramref name="propertyName"/>. If a matching property is
196+
/// found, the value is converted using <paramref name="callback"/>. If not found, an exception will be thrown instead.
197+
/// </summary>
198+
/// <param name="json">The parent JSON object.</param>
199+
/// <param name="propertyName">The name of the property.</param>
200+
/// <param name="callback">A callback function used for converting the 64-bit integer value to <typeparamref name="TResult"/>.</param>
201+
/// <returns>The <see cref="float"/> value.</returns>
202+
/// <exception cref="JsonPropertyNotFoundException">If a property matching <paramref name="propertyName"/> isn't found.</exception>
203+
/// <exception cref="JsonException">If the property is found, but the value doesn't match a 64-bit integer.</exception>
204+
public static TResult GetRequiredFloat<TResult>(this JObject json, string propertyName, Func<float, TResult> callback) where TResult : notnull {
205+
JProperty property = json.Property(propertyName) ?? throw new JsonPropertyNotFoundException(json, propertyName);
206+
if (!JsonTokenUtils.TryGetFloat(property.Value, out float result)) throw new JsonException($"The value of the '{propertyName}' property doesn't match a valid float value.");
207+
return callback(result);
208+
}
209+
177210
}

src/Skybrud.Essentials/Json/Newtonsoft/Extensions/NewtonsoftJsonObjectExtensions.Guid.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Diagnostics.CodeAnalysis;
33
using Newtonsoft.Json.Linq;
4+
using Skybrud.Essentials.Json.Newtonsoft.Exceptions;
45
using Skybrud.Essentials.Json.Newtonsoft.Parsing;
56

67
namespace Skybrud.Essentials.Json.Newtonsoft.Extensions;
@@ -179,4 +180,24 @@ public static Guid[] GetGuidArrayByPath(this JObject? json, string path) {
179180
return JsonTokenUtils.GetGuidArray(json?.SelectToken(path));
180181
}
181182

183+
/// <summary>
184+
/// Returns the GUID value of the property with the specified <paramref name="propertyName"/>. If a matching property isn't found, or the value isn't a valid GUID, an exception is thrown instead.
185+
/// </summary>
186+
/// <param name="json">The parent JSON object.</param>
187+
/// <param name="propertyName">The name of the property.</param>
188+
/// <returns>The <see cref="Guid"/>> value.</returns>
189+
/// <exception cref="JsonPropertyNotFoundException">If a property matching <paramref name="propertyName"/> isn't found.</exception>
190+
/// <exception cref="JsonException">If the property is found, but the value doesn't match a <see cref="Guid"/>.</exception>
191+
public static Guid GetRequiredGuid(this JObject json, string propertyName) {
192+
JProperty property = json.Property(propertyName) ?? throw new JsonPropertyNotFoundException(json, propertyName);
193+
if (!JsonTokenUtils.TryGetGuid(property.Value, out Guid result)) throw new JsonException($"The value of the '{propertyName}' property is not a valid GUID.");
194+
return result;
195+
}
196+
197+
public static TResult GetRequiredGuid<TResult>(this JObject json, string propertyName, Func<Guid, TResult> callback) where TResult : notnull {
198+
JProperty property = json.Property(propertyName) ?? throw new JsonPropertyNotFoundException(json, propertyName);
199+
if (!JsonTokenUtils.TryGetGuid(property.Value, out Guid result)) throw new JsonException($"The value of the '{propertyName}' property is not a valid GUID.");
200+
return callback(result);
201+
}
202+
182203
}

src/Skybrud.Essentials/Json/Newtonsoft/Extensions/NewtonsoftJsonObjectExtensions.Int16.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Diagnostics.CodeAnalysis;
33
using Newtonsoft.Json.Linq;
4+
using Skybrud.Essentials.Json.Newtonsoft.Exceptions;
45
using Skybrud.Essentials.Json.Newtonsoft.Parsing;
56

67
namespace Skybrud.Essentials.Json.Newtonsoft.Extensions;
@@ -174,4 +175,36 @@ public static short[] GetInt16ArrayByPath(this JObject? json, string path) {
174175
return JsonTokenUtils.GetInt16Array(json?.SelectToken(path));
175176
}
176177

178+
/// <summary>
179+
/// Returns the signed 16-bit integer value of the property with the specified <paramref name="propertyName"/>. If
180+
/// a matching property isn't found, or the value doesn't match a valid signed 16-bit integer, an exception is
181+
/// thrown instead.
182+
/// </summary>
183+
/// <param name="json">The parent JSON object.</param>
184+
/// <param name="propertyName">The name of the property.</param>
185+
/// <returns>The signed 16-bit integer value.</returns>
186+
/// <exception cref="JsonPropertyNotFoundException">If a property matching <paramref name="propertyName"/> isn't found.</exception>
187+
/// <exception cref="JsonException">If the property is found, but the value doesn't match a signed 16-bit integer.</exception>
188+
public static int GetRequiredInt16(this JObject json, string propertyName) {
189+
JProperty property = json.Property(propertyName) ?? throw new JsonPropertyNotFoundException(json, propertyName);
190+
if (!JsonTokenUtils.TryGetInt16(property.Value, out short result)) throw new JsonException($"The value of the '{propertyName}' property doesn't match a valid 16-bit integer value.");
191+
return result;
192+
}
193+
194+
/// <summary>
195+
/// Returns the value of the property with the specified <paramref name="propertyName"/>. If a matching property is
196+
/// found, the value is converted using <paramref name="callback"/>. If not found, an exception will be thrown instead.
197+
/// </summary>
198+
/// <param name="json">The parent JSON object.</param>
199+
/// <param name="propertyName">The name of the property.</param>
200+
/// <param name="callback">A callback function used for converting the signed 16-bit integer value to <typeparamref name="TResult"/>.</param>
201+
/// <returns>The signed 16-bit integer value.</returns>
202+
/// <exception cref="JsonPropertyNotFoundException">If a property matching <paramref name="propertyName"/> isn't found.</exception>
203+
/// <exception cref="JsonException">If the property is found, but the value doesn't match a signed 16-bit integer.</exception>
204+
public static TResult GetRequiredInt16<TResult>(this JObject json, string propertyName, Func<int, TResult> callback) where TResult : notnull {
205+
JProperty property = json.Property(propertyName) ?? throw new JsonPropertyNotFoundException(json, propertyName);
206+
if (!JsonTokenUtils.TryGetInt16(property.Value, out short result)) throw new JsonException($"The value of the '{propertyName}' property doesn't match a valid 16-bit integer value.");
207+
return callback(result);
208+
}
209+
177210
}

0 commit comments

Comments
 (0)