< 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
66%
Covered lines: 91
Uncovered lines: 45
Coverable lines: 136
Total lines: 216
Line coverage: 66.9%
Branch coverage
65%
Covered branches: 61
Total branches: 93
Branch coverage: 65.5%
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(...)38.09%312171.42%
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) 2026 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{
 2120    private static readonly Type TargetType = typeof(T);
 21
 22    public static T Parse(string json)
 446323    {
 446324        using var jsonDocument = JsonDocument.Parse(json, JsonHelperOptions.JsonDocumentOptions);
 25
 446326        var result = DeserializeElement(jsonDocument.RootElement, TargetType);
 27
 446328        return result switch
 446329        {
 430            null when !typeof(T).IsValueType || Nullable.GetUnderlyingType(typeof(T)) is not null => default!,
 446131            T t => t,
 032            _ => throw new JsonException($"JsonHelper<{TargetType.Name}>: could not convert JSON to {TargetType}.")
 446333        };
 446334    }
 35
 36    private static object? DeserializeElement(JsonElement jsonElement, Type type)
 3067737    {
 3067738        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
 358639        {
 358640            if (jsonElement.ValueKind == JsonValueKind.Null)
 80341            {
 80342                return null;
 43            }
 44
 278345            type = Nullable.GetUnderlyingType(type)!;
 278346        }
 47
 2987448        if (type == typeof(object))
 50049        {
 50050            return ConvertElement(jsonElement);
 51        }
 52
 2937453        if (IsPrimitiveType(type))
 2181054        {
 2181055            return ConvertToPrimitive(jsonElement, type);
 56        }
 57
 756458        if (type.IsArray)
 650859        {
 650860            return DeserializeArray(jsonElement, type.GetElementType()!);
 61        }
 62
 105663        if (IsListType(type, out var itemType))
 064        {
 065            return DeserializeList(jsonElement, type, itemType);
 66        }
 67
 105668        if (IsDictionaryType(type, out var valueType))
 069        {
 070            return DeserializeDictionary(jsonElement, type, valueType);
 71        }
 72
 105673        return JsonSerializer.Deserialize(jsonElement.GetRawText(), type, JsonHelperOptions.JsonSerializerOptions) ??
 105674               throw new JsonException($"Unable to deserialize JSON to {type}.");
 3067775    }
 76
 77    private static bool IsPrimitiveType(Type type)
 2937478    {
 2937479        return type == typeof(string) ||
 2937480               type == typeof(bool) ||
 2937481               type == typeof(int) ||
 2937482               type == typeof(long) ||
 2937483               type == typeof(double) ||
 2937484               type == typeof(decimal);
 2937485    }
 86
 87    private static object? ConvertToPrimitive(JsonElement jsonElement, Type type)
 2181088    {
 2181089        return type switch
 2181090        {
 2333491            _ when type == typeof(string) => jsonElement.GetString(),
 2036892            _ when type == typeof(bool) => jsonElement.GetBoolean(),
 4031293            _ when type == typeof(int) => jsonElement.GetInt32(),
 10294            _ 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)
 2181098        };
 2181099    }
 100
 101    private static Array DeserializeArray(JsonElement jsonElement, Type type)
 6508102    {
 6508103        if (jsonElement.ValueKind != JsonValueKind.Array)
 0104        {
 0105            throw new JsonException($"Expected JSON array for {type}[]");
 106        }
 107
 6508108        var items = jsonElement.EnumerateArray()
 26214109            .Select(item => DeserializeElement(item, type))
 6508110            .ToArray();
 111
 6508112        var array = Array.CreateInstance(type, items.Length);
 113
 65444114        for (var i = 0; i < items.Length; i++)
 26214115        {
 26214116            array.SetValue(items[i], i);
 26214117        }
 118
 6508119        return array;
 6508120    }
 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)
 518159    {
 518160        return jsonElement.ValueKind switch
 518161        {
 0162            JsonValueKind.Object => jsonElement.EnumerateObject()
 0163                .ToDictionary(p => p.Name, p => ConvertElement(p.Value)),
 9164            JsonValueKind.Array => jsonElement.EnumerateArray()
 9165                .Select(ConvertElement)
 9166                .ToArray(),
 76167            JsonValueKind.String => jsonElement.GetString(),
 343168            JsonValueKind.Number => jsonElement.TryGetInt32(out var i) ? i
 343169                : jsonElement.TryGetInt64(out var l) ? l
 343170                : jsonElement.TryGetDecimal(out var d) ? d
 343171                : jsonElement.GetDouble(),
 64172            JsonValueKind.True => true,
 26173            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}")
 518178        };
 518179    }
 180
 181    private static bool IsListType(Type type, out Type itemType)
 1056182    {
 1056183        var iListType = type.GetInterfaces()
 33234184            .FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList<>));
 185
 1056186        if (iListType != null)
 0187        {
 0188            itemType = iListType.GetGenericArguments()[0];
 189
 0190            return true;
 191        }
 192
 1056193        itemType = null!;
 194
 1056195        return false;
 1056196    }
 197
 198    private static bool IsDictionaryType(Type type, out Type valueType)
 1056199    {
 1056200        var iDictionaryType = type.GetInterfaces()
 33234201            .FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IDictionary<,>));
 202
 1056203        if (iDictionaryType != null)
 0204        {
 0205            var args = iDictionaryType.GetGenericArguments();
 206
 0207            valueType = args[1];
 208
 0209            return true;
 210        }
 211
 1056212        valueType = null!;
 213
 1056214        return false;
 1056215    }
 216}