private T PerformWithSettings <T>(Func <JsonSerializerSettings, T> func)
    {
        JsonSerializerSettings settings;

        bool recursive = false;

        if (currentJsonSettings.Value != null)
        {
            // This is a recursive call
            recursive = true;
            settings  = currentJsonSettings.Value;

            settings.TraceWriter?.Trace(TraceLevel.Info, "Entering recursive object", null);
        }
        else
        {
            settings = CreateSettings();
            currentJsonSettings.Value = settings;
        }

        try
        {
            return(func(settings));
        }
        catch (Exception e)
        {
            // Don't do our special automatic debug enabling if debug writing is already on
            if (JSONDebug.ErrorHasOccurred || settings.TraceWriter != null)
            {
                throw;
            }

            JSONDebug.ErrorHasOccurred = true;

            if (Settings.Instance.JSONDebugMode == JSONDebug.DebugMode.Automatic)
            {
                GD.Print("JSON error happened, retrying with debug printing (mode is automatic), first exception: ",
                         e);

                currentJsonSettings.Value = null;
                PerformWithSettings(func);

                // If we get here, we didn't get another exception...
                // So we could maybe re-throw the first exception so that we fail like we should
                GD.PrintErr(
                    "Expected an exception for the second try at JSON operation, but it succeeded, " +
                    "re-throwing the original exception");
                throw;
            }
            else
            {
                throw;
            }
        }
        finally
        {
            if (!recursive)
            {
                currentJsonSettings.Value = null;

                if (settings.TraceWriter != null)
                {
                    JSONDebug.OnTraceFinished(settings.TraceWriter);

                    // This shouldn't get reused so no point in creating a new instance here
                    settings.TraceWriter = null;
                }
            }
            else
            {
                settings.TraceWriter?.Trace(TraceLevel.Info, "Exited recursive object", null);
            }
        }
    }