From d02bebc6e28640fa003edc004b203fff9aab3c83 Mon Sep 17 00:00:00 2001 From: TekH Date: Thu, 4 Dec 2025 13:44:10 +0100 Subject: [PATCH] Refactor and enhance JSON handling with extensions Refactored `ConfigExtensions.cs` to move `ConfigurationExtensions` to the `ReC.API.Extensions` namespace and re-added the `GetFakeProfileId` method. Introduced `JsonExtensions.cs` with a `JsonToDynamic` method for recursive JSON deserialization, simplifying nested JSON handling. Updated `OutResController.cs` and `RecActionController.cs` to use the new `JsonToDynamic` method, improving code readability and reducing duplication. Overall, modularized and cleaned up code for better maintainability. --- src/ReC.API/Controllers/OutResController.cs | 7 +-- .../Controllers/RecActionController.cs | 1 + .../{ => Extensions}/ConfigExtensions.cs | 4 +- src/ReC.API/Extensions/JsonExtensions.cs | 56 +++++++++++++++++++ 4 files changed, 62 insertions(+), 6 deletions(-) rename src/ReC.API/{ => Extensions}/ConfigExtensions.cs (59%) create mode 100644 src/ReC.API/Extensions/JsonExtensions.cs diff --git a/src/ReC.API/Controllers/OutResController.cs b/src/ReC.API/Controllers/OutResController.cs index a7594a1..7c81d09 100644 --- a/src/ReC.API/Controllers/OutResController.cs +++ b/src/ReC.API/Controllers/OutResController.cs @@ -1,9 +1,8 @@ using MediatR; using Microsoft.AspNetCore.Mvc; -using ReC.API.Models; +using ReC.API.Extensions; using ReC.Application.OutResults.Queries; using System.Net.Mime; -using System.Text.Json; namespace ReC.API.Controllers; @@ -34,8 +33,8 @@ public class OutResController(IMediator mediator, IConfiguration config) : Contr return resultType switch { - ResultType.Body => res.Body is null ? Ok(new object { }) : Ok(JsonSerializer.Deserialize(res.Body)), - ResultType.Header => res.Header is null ? Ok(new object { }) : Ok(JsonSerializer.Deserialize(res.Header)), + ResultType.Body => res.Body is null ? Ok(new object { }) : Ok(res.Body.JsonToDynamic()), + ResultType.Header => res.Header is null ? Ok(new object { }) : Ok(res.Header.JsonToDynamic()), _ => Ok(res), }; } diff --git a/src/ReC.API/Controllers/RecActionController.cs b/src/ReC.API/Controllers/RecActionController.cs index 49f1bc4..f1428fe 100644 --- a/src/ReC.API/Controllers/RecActionController.cs +++ b/src/ReC.API/Controllers/RecActionController.cs @@ -1,5 +1,6 @@ using MediatR; using Microsoft.AspNetCore.Mvc; +using ReC.API.Extensions; using ReC.API.Models; using ReC.Application.RecActions.Commands; using ReC.Application.RecActions.Queries; diff --git a/src/ReC.API/ConfigExtensions.cs b/src/ReC.API/Extensions/ConfigExtensions.cs similarity index 59% rename from src/ReC.API/ConfigExtensions.cs rename to src/ReC.API/Extensions/ConfigExtensions.cs index aeb9345..262830c 100644 --- a/src/ReC.API/ConfigExtensions.cs +++ b/src/ReC.API/Extensions/ConfigExtensions.cs @@ -1,6 +1,6 @@ -namespace ReC.API; +namespace ReC.API.Extensions; public static class ConfigurationExtensions { - public static int GetFakeProfileId(this IConfiguration config) => config.GetValue("FakeProfileId", 2); + public static int GetFakeProfileId(this IConfiguration config) => config.GetValue("FakeProfileId", 2); } diff --git a/src/ReC.API/Extensions/JsonExtensions.cs b/src/ReC.API/Extensions/JsonExtensions.cs new file mode 100644 index 0000000..95d3140 --- /dev/null +++ b/src/ReC.API/Extensions/JsonExtensions.cs @@ -0,0 +1,56 @@ +using System.Text.Json; + +public static class JsonExtensions +{ + /// + /// Deserialize JSON string and automatically parse nested JSON strings. + /// + public static dynamic? JsonToDynamic(this string json) + { + // Deserialize the top-level JSON + var result = JsonSerializer.Deserialize(json); + + // Recursively fix stringified JSON objects + return JsonToDynamic(result); + } + + private static dynamic? JsonToDynamic(JsonElement obj) + { + switch (obj.ValueKind) + { + case JsonValueKind.Object: + var dict = new Dictionary(); + foreach (var prop in obj.EnumerateObject()) + { + dict[prop.Name] = JsonToDynamic(prop.Value); + } + return dict; + + case JsonValueKind.Array: + var list = new List(); + foreach (var item in obj.EnumerateArray()) + { + list.Add(JsonToDynamic(item)); + } + return list; + + case JsonValueKind.String: + var str = obj.GetString(); + // Try to parse string as JSON + if (!string.IsNullOrWhiteSpace(str) && (str.StartsWith('{') || str.StartsWith('['))) + { + try + { + return JsonToDynamic(JsonSerializer.Deserialize(str)); + } + catch + { + return str; // Not valid JSON, return original string + } + } + return str; + default: + return obj.GetRawText(); + } + } +}