< Summary

Information
Class: LeetCode.Core.Helpers.JsonHelper<T>
Assembly: LeetCode.Core
File(s): D:\a\LeetCode-CS\LeetCode-CS\source\LeetCode.Core\Helpers\JsonHelper.cs
Line coverage
64%
Covered lines: 88
Uncovered lines: 48
Coverable lines: 136
Total lines: 216
Line coverage: 64.7%
Branch coverage
62%
Covered branches: 58
Total branches: 93
Branch coverage: 62.3%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
Parse(...)75%8890%
DeserializeElement(...)83.33%191884.61%
IsPrimitiveType(...)100%1010100%
ConvertToPrimitive(...)75%131283.33%
DeserializeArray(...)75%4485.71%
DeserializeList(...)0%2040%
DeserializeDictionary(...)0%2040%
ConvertElement(...)23.8%562157.14%
IsListType(...)83.33%7670%
IsDictionaryType(...)83.33%8663.63%

File(s)

D:\a\LeetCode-CS\LeetCode-CS\source\LeetCode.Core\Helpers\JsonHelper.cs

#LineLine coverage
 1// --------------------------------------------------------------------------------
 2// Copyright (C) 2025 Eugene Eremeev (also known as Yevhenii Yeriemeieiv).
 3// All Rights Reserved.
 4// --------------------------------------------------------------------------------
 5// This software is the confidential and proprietary information of Eugene Eremeev
 6// (also known as Yevhenii Yeriemeieiv) ("Confidential Information"). You shall not
 7// disclose such Confidential Information and shall use it only in accordance with
 8// the terms of the license agreement you entered into with Eugene Eremeev (also
 9// known as Yevhenii Yeriemeieiv).
 10// --------------------------------------------------------------------------------
 11
 12using System.Collections;
 13using System.Globalization;
 14using System.Text.Json;
 15
 16namespace LeetCode.Core.Helpers;
 17
 18public static class JsonHelper<T>
 19{
 1920    private static readonly Type TargetType = typeof(T);
 21
 22    public static T Parse(string json)
 386123    {
 386124        using var jsonDocument = JsonDocument.Parse(json, JsonHelperOptions.JsonDocumentOptions);
 25
 386126        var result = DeserializeElement(jsonDocument.RootElement, TargetType);
 27
 386128        return result switch
 386129        {
 430            null when !typeof(T).IsValueType || Nullable.GetUnderlyingType(typeof(T)) is not null => default!,
 385931            T t => t,
 032            _ => throw new JsonException($"JsonHelper<{TargetType.Name}>: could not convert JSON to {TargetType}.")
 386133        };
 386134    }
 35
 36    private static object? DeserializeElement(JsonElement jsonElement, Type type)
 2582037    {
 2582038        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
 352339        {
 352340            if (jsonElement.ValueKind == JsonValueKind.Null)
 78741            {
 78742                return null;
 43            }
 44
 273645            type = Nullable.GetUnderlyingType(type)!;
 273646        }
 47
 2503348        if (type == typeof(object))
 24949        {
 24950            return ConvertElement(jsonElement);
 51        }
 52
 2478453        if (IsPrimitiveType(type))
 1916454        {
 1916455            return ConvertToPrimitive(jsonElement, type);
 56        }
 57
 562058        if (type.IsArray)
 532659        {
 532660            return DeserializeArray(jsonElement, type.GetElementType()!);
 61        }
 62
 29463        if (IsListType(type, out var itemType))
 064        {
 065            return DeserializeList(jsonElement, type, itemType);
 66        }
 67
 29468        if (IsDictionaryType(type, out var valueType))
 069        {
 070            return DeserializeDictionary(jsonElement, type, valueType);
 71        }
 72
 29473        return JsonSerializer.Deserialize(jsonElement.GetRawText(), type, JsonHelperOptions.JsonSerializerOptions) ??
 29474               throw new JsonException($"Unable to deserialize JSON to {type}.");
 2582075    }
 76
 77    private static bool IsPrimitiveType(Type type)
 2478478    {
 2478479        return type == typeof(string) ||
 2478480               type == typeof(bool) ||
 2478481               type == typeof(int) ||
 2478482               type == typeof(long) ||
 2478483               type == typeof(double) ||
 2478484               type == typeof(decimal);
 2478485    }
 86
 87    private static object? ConvertToPrimitive(JsonElement jsonElement, Type type)
 1916488    {
 1916489        return type switch
 1916490        {
 2039091            _ when type == typeof(string) => jsonElement.GetString(),
 1800692            _ when type == typeof(bool) => jsonElement.GetBoolean(),
 3564993            _ when type == typeof(int) => jsonElement.GetInt32(),
 9294            _ when type == typeof(long) => jsonElement.GetInt64(),
 18095            _ when type == typeof(double) => jsonElement.GetDouble(),
 096            _ when type == typeof(decimal) => jsonElement.GetDecimal(),
 097            _ => Convert.ChangeType(ConvertElement(jsonElement), type, CultureInfo.InvariantCulture)
 1916498        };
 1916499    }
 100
 101    private static Array DeserializeArray(JsonElement jsonElement, Type type)
 5326102    {
 5326103        if (jsonElement.ValueKind != JsonValueKind.Array)
 0104        {
 0105            throw new JsonException($"Expected JSON array for {type}[]");
 106        }
 107
 5326108        var items = jsonElement.EnumerateArray()
 21959109            .Select(item => DeserializeElement(item, type))
 5326110            .ToArray();
 111
 5326112        var array = Array.CreateInstance(type, items.Length);
 113
 54570114        for (var i = 0; i < items.Length; i++)
 21959115        {
 21959116            array.SetValue(items[i], i);
 21959117        }
 118
 5326119        return array;
 5326120    }
 121
 122    private static IList DeserializeList(JsonElement jsonElement, Type listType, Type itemType)
 0123    {
 0124        if (jsonElement.ValueKind != JsonValueKind.Array)
 0125        {
 0126            throw new JsonException($"Expected JSON array for {listType.Name}");
 127        }
 128
 0129        var list = (IList)Activator.CreateInstance(listType)!;
 130
 0131        foreach (var item in jsonElement.EnumerateArray())
 0132        {
 0133            list.Add(DeserializeElement(item, itemType));
 0134        }
 135
 0136        return list;
 0137    }
 138
 139    private static IDictionary DeserializeDictionary(JsonElement jsonElement, Type dictionaryType, Type valueType)
 0140    {
 0141        if (jsonElement.ValueKind != JsonValueKind.Object)
 0142        {
 0143            throw new JsonException($"Expected JSON object for {dictionaryType.Name}");
 144        }
 145
 0146        var dictionary = (IDictionary)Activator.CreateInstance(dictionaryType)!;
 147
 0148        foreach (var property in jsonElement.EnumerateObject())
 0149        {
 0150            var value = DeserializeElement(property.Value, valueType);
 151
 0152            dictionary.Add(property.Name, value);
 0153        }
 154
 0155        return dictionary;
 0156    }
 157
 158    private static object? ConvertElement(JsonElement jsonElement)
 249159    {
 249160        return jsonElement.ValueKind switch
 249161        {
 0162            JsonValueKind.Object => jsonElement.EnumerateObject()
 0163                .ToDictionary(p => p.Name, p => ConvertElement(p.Value)),
 0164            JsonValueKind.Array => jsonElement.EnumerateArray()
 0165                .Select(ConvertElement)
 0166                .ToArray(),
 43167            JsonValueKind.String => jsonElement.GetString(),
 174168            JsonValueKind.Number => jsonElement.TryGetInt32(out var i) ? i
 174169                : jsonElement.TryGetInt64(out var l) ? l
 174170                : jsonElement.TryGetDecimal(out var d) ? d
 174171                : jsonElement.GetDouble(),
 22172            JsonValueKind.True => true,
 10173            JsonValueKind.False => false,
 0174            JsonValueKind.Null => null,
 0175            JsonValueKind.Undefined => throw new JsonException(
 0176                "Encountered undefined JSON element—likely a missing property or uninitialized JsonElement"),
 0177            _ => throw new NotSupportedException($"Unsupported JSON kind: {jsonElement.ValueKind}")
 249178        };
 249179    }
 180
 181    private static bool IsListType(Type type, out Type itemType)
 294182    {
 294183        var iListType = type.GetInterfaces()
 7716184            .FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList<>));
 185
 294186        if (iListType != null)
 0187        {
 0188            itemType = iListType.GetGenericArguments()[0];
 189
 0190            return true;
 191        }
 192
 294193        itemType = null!;
 194
 294195        return false;
 294196    }
 197
 198    private static bool IsDictionaryType(Type type, out Type valueType)
 294199    {
 294200        var iDictionaryType = type.GetInterfaces()
 7716201            .FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IDictionary<,>));
 202
 294203        if (iDictionaryType != null)
 0204        {
 0205            var args = iDictionaryType.GetGenericArguments();
 206
 0207            valueType = args[1];
 208
 0209            return true;
 210        }
 211
 294212        valueType = null!;
 213
 294214        return false;
 294215    }
 216}