Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Frends.JSON.ConvertJSONStringToJToken/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## [1.2.0] - 2026-08-04
### Changed
- The task now targets .NET 8.
- Added error handling options: you can now choose whether the task throws an error on failure or returns a result with `Success = false` and error details in the `Error` property.
- The result now includes an `Error` property with details when the task fails.

## [1.1.0] - 2024-08-20
### Updated
- Updated Newtonsoft.Json library to the latest version 13.0.3.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using Frends.JSON.ConvertJSONStringToJToken.Definitions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Threading;

namespace Frends.JSON.ConvertJSONStringToJToken.UnitTests;

[TestClass]
public class ErrorHandlerTests
{
private const string CustomErrorMessage = "CustomErrorMessage";

private static Input InvalidInput() => new Input { Json = "not valid json{{" };
private static Options DefaultOptions() => new Options { ThrowErrorOnFailure = true };

[TestMethod]
public void Should_Throw_Error_When_ThrowErrorOnFailure_Is_True()
{
var ex = Assert.ThrowsException<Exception>(() =>
JSON.ConvertJSONStringToJToken(InvalidInput(), DefaultOptions(), CancellationToken.None));
Assert.IsNotNull(ex);
}

[TestMethod]
public void Should_Return_Failed_Result_When_ThrowErrorOnFailure_Is_False()
{
var options = DefaultOptions();
options.ThrowErrorOnFailure = false;
var result = JSON.ConvertJSONStringToJToken(InvalidInput(), options, CancellationToken.None);
Assert.IsFalse(result.Success);
Assert.IsNotNull(result.Error);
}

[TestMethod]
public void Should_Use_Custom_ErrorMessageOnFailure()
{
var options = DefaultOptions();
options.ErrorMessageOnFailure = CustomErrorMessage;
var ex = Assert.ThrowsException<Exception>(() =>
JSON.ConvertJSONStringToJToken(InvalidInput(), options, CancellationToken.None));
Assert.IsNotNull(ex);
StringAssert.Contains(ex.Message, CustomErrorMessage);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
using Frends.JSON.ConvertJSONStringToJToken.Definitions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json.Linq;
using System.Threading;

namespace Frends.JSON.ConvertJSONStringToJToken.UnitTests;

[TestClass]
public class UnitTests
{
private static Options DefaultOptions() => new Options { ThrowErrorOnFailure = true };

[TestMethod]
public void ShouldConvertJsonStringToJToken()
{
Expand All @@ -15,9 +18,9 @@ public void ShouldConvertJsonStringToJToken()
Json = @"{ 'foo': 'bar', 'foobar': ['Foo', 'Bar'] }"
};

var result = JSON.ConvertJSONStringToJToken(input);
var result = JSON.ConvertJSONStringToJToken(input, DefaultOptions(), CancellationToken.None);
Assert.AreEqual("bar", result.Jtoken.foo.ToString());
Assert.IsTrue(result.Success);
Assert.IsInstanceOfType(result.Jtoken, typeof(JObject));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,35 @@
using Frends.JSON.ConvertJSONStringToJToken.Definitions;
using Frends.JSON.ConvertJSONStringToJToken.Helpers;
using Newtonsoft.Json.Linq;
using System;
using System.ComponentModel;
using System.Threading;

namespace Frends.JSON.ConvertJSONStringToJToken;

/// <summary>
/// JSON Task.
/// </summary>
public class JSON
public static class JSON
{
/// <summary>
/// Convert JSON string to JToken.
/// [Documentation](https://tasks.frends.com/tasks/frends-tasks/Frends.JSON.ConvertJSONStringToJToken)
/// </summary>
/// <param name="input">Input parameters</param>
/// <returns>Object { bool Success, dynamic Jtoken }</returns>
public static Result ConvertJSONStringToJToken([PropertyTab] Input input)
/// <param name="options">Options for error handling</param>
/// <param name="cancellationToken">Token to cancel the operation</param>
/// <returns>Object { bool Success, dynamic Jtoken, Error Error }</returns>
public static Result ConvertJSONStringToJToken([PropertyTab] Input input, [PropertyTab] Options options, CancellationToken cancellationToken)
{
return new Result(true, JToken.Parse(input.Json));
try
{
cancellationToken.ThrowIfCancellationRequested();
return new Result { Success = true, Jtoken = JToken.Parse(input.Json) };
}
catch (Exception ex)
{
return ex.Handle(options);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;

namespace Frends.JSON.ConvertJSONStringToJToken.Definitions;

/// <summary>
/// Error information.
/// </summary>
public class Error
{
/// <summary>
/// Error message.
/// </summary>
/// <example>An error occurred.</example>
public string Message { get; init; }

/// <summary>
/// Additional error information.
/// </summary>
public Exception AdditionalInfo { get; init; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace Frends.JSON.ConvertJSONStringToJToken.Definitions;

/// <summary>
/// Options for the task.
/// </summary>
public class Options
{
/// <summary>
/// Whether to throw an error on failure or return a result with Success = false.
/// </summary>
/// <example>true</example>
[DefaultValue(true)]
public bool ThrowErrorOnFailure { get; set; } = true;

/// <summary>
/// Custom error message to use when ThrowErrorOnFailure is true.
/// </summary>
/// <example></example>
[DisplayFormat(DataFormatString = "Text")]
[DefaultValue("")]
public string ErrorMessageOnFailure { get; set; } = string.Empty;
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,16 @@ public class Result
/// Operation complete without errors.
/// </summary>
/// <example>true</example>
public bool Success { get; private set; }
public bool Success { get; init; }

/// <summary>
/// JToken.
/// </summary>
/// <example>{{ "foo": "bar", "foobar": [ "Foo", "Bar" ]}}</example>
public dynamic Jtoken { get; private set; }
public dynamic Jtoken { get; init; }

internal Result(bool success, object jtoken)
{
Success = success;
Jtoken = jtoken;
}
/// <summary>
/// Error information if the operation failed.
/// </summary>
public Error Error { get; init; }
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net6.0</TargetFrameworks>
<Version>1.1.0</Version>
<TargetFrameworks>net8.0</TargetFrameworks>
<Version>1.2.0</Version>
<Authors>Frends</Authors>
<Copyright>Frends</Copyright>
<Company>Frends</Company>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using Frends.JSON.ConvertJSONStringToJToken.Definitions;
using System;

namespace Frends.JSON.ConvertJSONStringToJToken.Helpers;

internal static class ErrorHandler
{
internal static Result Handle(this Exception exception, Options options, bool throwCanceled = true)
{
ThrowIfCanceled(exception, throwCanceled);
if (options.ThrowErrorOnFailure) ThrowBaseException(exception, options.ErrorMessageOnFailure);

return ReturnResult(exception, options.ErrorMessageOnFailure);
}

private static void ThrowIfCanceled(Exception exception, bool throwCanceled = true)
{
if (throwCanceled && exception is OperationCanceledException) throw exception;
}

private static void ThrowBaseException(Exception exception, string customMessage = null)
{
if (string.IsNullOrEmpty(customMessage))
throw new Exception(exception.Message, exception);

throw new Exception(customMessage, exception);
}

private static Result ReturnResult(Exception exception, string customMessage = null)
{
var errorMessage = string.IsNullOrEmpty(customMessage)
? exception.Message
: $"{customMessage}: {exception.Message}";

return new Result
{
Success = false,
Error = new Error
{
Message = errorMessage,
AdditionalInfo = exception,
},
};
}
}
Loading