ktsu.RoundTripStringJsonConverter 1.0.2

Prefix Reserved
There is a newer version of this package available.
See the version list below for details.
dotnet add package ktsu.RoundTripStringJsonConverter --version 1.0.2
                    
NuGet\Install-Package ktsu.RoundTripStringJsonConverter -Version 1.0.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ktsu.RoundTripStringJsonConverter" Version="1.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ktsu.RoundTripStringJsonConverter" Version="1.0.2" />
                    
Directory.Packages.props
<PackageReference Include="ktsu.RoundTripStringJsonConverter" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ktsu.RoundTripStringJsonConverter --version 1.0.2
                    
#r "nuget: ktsu.RoundTripStringJsonConverter, 1.0.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ktsu.RoundTripStringJsonConverter@1.0.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ktsu.RoundTripStringJsonConverter&version=1.0.2
                    
Install as a Cake Addin
#tool nuget:?package=ktsu.RoundTripStringJsonConverter&version=1.0.2
                    
Install as a Cake Tool

ktsu.RoundTripStringJsonConverter

A versatile JSON converter factory that serializes objects using their ToString method and deserializes using FromString, Parse, Create, or Convert methods.

License NuGet NuGet Downloads Build Status GitHub Stars

Introduction

RoundTripStringJsonConverter is a powerful JSON converter factory for System.Text.Json that simplifies serialization and deserialization of custom types by leveraging their string representation methods. It automatically detects and uses the most appropriate conversion method from a prioritized list: FromString, Parse, Create, or Convert. This approach is particularly useful for value types, strong types, domain objects, and any other types where a string representation makes logical sense.

Features

  • Multiple Conversion Methods: Supports FromString, Parse, Create, and Convert methods with intelligent priority selection
  • Automatic Type Detection: Automatically identifies types with compatible conversion methods
  • Method Priority System: Uses FromString first, then Parse, Create, and finally Convert
  • String-Based Serialization: Converts objects to and from JSON using their string representation
  • Property Name Support: Works with both JSON values and property names (dictionary keys)
  • Reflection Optimization: Uses cached reflection for improved performance
  • Generic Method Support: Handles both generic and non-generic conversion methods
  • Comprehensive Error Handling: Graceful handling of invalid types and conversion failures

Installation

Package Manager Console

Install-Package ktsu.RoundTripStringJsonConverter

.NET CLI

dotnet add package ktsu.RoundTripStringJsonConverter

Package Reference

<PackageReference Include="ktsu.RoundTripStringJsonConverter" Version="x.y.z" />

Usage Examples

Basic Example with FromString

using System.Text.Json;
using ktsu.RoundTripStringJsonConverter;

// Configure the converter in your JsonSerializerOptions
var options = new JsonSerializerOptions();
options.Converters.Add(new RoundTripStringJsonConverterFactory());

// Example custom type with ToString and FromString
public class UserId
{
    public string Value { get; set; }
    
    public static UserId FromString(string value) => new() { Value = value };
    
    public override string ToString() => Value;
}

// Serialization
var userId = new UserId { Value = "USER-12345" };
string json = JsonSerializer.Serialize(userId, options);
// json is now: "USER-12345"

// Deserialization
UserId deserialized = JsonSerializer.Deserialize<UserId>(json, options);
// deserialized.Value is now: "USER-12345"

Using Different Conversion Methods

The converter automatically detects and uses the appropriate method based on priority:

// Type with Parse method (common in .NET)
public class ProductCode
{
    public string Code { get; set; }
    
    public static ProductCode Parse(string code) => new() { Code = code };
    
    public override string ToString() => Code;
}

// Type with Create method (factory pattern)
public class OrderId
{
    public string Id { get; set; }
    
    public static OrderId Create(string id) => new() { Id = id };
    
    public override string ToString() => Id;
}

// Type with Convert method
public class CategoryName
{
    public string Name { get; set; }
    
    public static CategoryName Convert(string name) => new() { Name = name };
    
    public override string ToString() => Name;
}

// All types work seamlessly with the same converter
var options = new JsonSerializerOptions();
options.Converters.Add(new RoundTripStringJsonConverterFactory());

var product = ProductCode.Parse("PROD-ABC");
var order = OrderId.Create("ORD-001");
var category = CategoryName.Convert("Electronics");

// All serialize and deserialize correctly
string productJson = JsonSerializer.Serialize(product, options);
string orderJson = JsonSerializer.Serialize(order, options);
string categoryJson = JsonSerializer.Serialize(category, options);

Method Priority Example

When multiple methods are available, the converter uses this priority order:

public class MultiMethodType
{
    public string Value { get; set; }
    
    // Highest priority - will be used
    public static MultiMethodType FromString(string value) => new() { Value = $"FromString:{value}" };
    
    // Lower priority - will be ignored
    public static MultiMethodType Parse(string value) => new() { Value = $"Parse:{value}" };
    
    public override string ToString() => Value;
}

// FromString method will be used for deserialization
var result = JsonSerializer.Deserialize<MultiMethodType>("\"test\"", options);
// result.Value will be "FromString:test"

Integration with Other Converters

using System.Text.Json;
using System.Text.Json.Serialization;
using ktsu.RoundTripStringJsonConverter;

var options = new JsonSerializerOptions
{
    WriteIndented = true,
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
    Converters =
    {
        new RoundTripStringJsonConverterFactory(),
        new JsonStringEnumConverter()
    }
};

// Now both enum values and custom types with conversion methods will be handled appropriately

Advanced Usage

Working with Collections of Custom Types

using System.Text.Json;
using ktsu.RoundTripStringJsonConverter;

// Setup serializer options with the converter
var options = new JsonSerializerOptions();
options.Converters.Add(new RoundTripStringJsonConverterFactory());

// A collection of custom types
List<UserId> userIds = new()
{
    UserId.FromString("USER-001"),
    UserId.FromString("USER-002"),
    UserId.FromString("USER-003")
};

// Serialize the collection
string json = JsonSerializer.Serialize(userIds, options);
// json is now: ["USER-001","USER-002","USER-003"]

// Deserialize back to a collection
List<UserId> deserializedIds = JsonSerializer.Deserialize<List<UserId>>(json, options);

Using with Dictionaries as Keys

// Custom types can be used as dictionary keys
var userProducts = new Dictionary<UserId, List<ProductCode>>
{
    { UserId.FromString("USER-001"), [ProductCode.Parse("PROD-A"), ProductCode.Parse("PROD-B")] },
    { UserId.FromString("USER-002"), [ProductCode.Parse("PROD-C")] }
};

string json = JsonSerializer.Serialize(userProducts, options);
// Serializes as a dictionary with string keys

var deserialized = JsonSerializer.Deserialize<Dictionary<UserId, List<ProductCode>>>(json, options);
// Keys are properly deserialized back to UserId objects

Complex Domain Objects

public class Order
{
    public OrderId Id { get; set; }
    public UserId CustomerId { get; set; }
    public List<ProductCode> Products { get; set; }
    public Dictionary<CategoryName, int> CategoryCounts { get; set; }
    public DateTime OrderDate { get; set; }
}

// All custom types are automatically handled
var order = new Order
{
    Id = OrderId.Create("ORD-001"),
    CustomerId = UserId.FromString("USER-123"),
    Products = [ProductCode.Parse("PROD-A"), ProductCode.Parse("PROD-B")],
    CategoryCounts = new Dictionary<CategoryName, int>
    {
        { CategoryName.Convert("Electronics"), 2 }
    },
    OrderDate = DateTime.UtcNow
};

string json = JsonSerializer.Serialize(order, options);
Order deserializedOrder = JsonSerializer.Deserialize<Order>(json, options);

API Reference

RoundTripStringJsonConverterFactory

The primary class for integrating with System.Text.Json serialization.

Methods
Name Return Type Description
CanConvert(Type typeToConvert) bool Determines if a type can be converted by checking for compatible conversion methods
CreateConverter(Type typeToConvert, JsonSerializerOptions options) JsonConverter Creates a type-specific converter instance

Supported Conversion Methods

The converter looks for static methods in this priority order:

  1. FromString(string) - Highest priority, commonly used for custom types
  2. Parse(string) - Second priority, follows .NET conventions (like int.Parse)
  3. Create(string) - Third priority, factory pattern methods
  4. Convert(string) - Lowest priority, general conversion methods

Compatibility Requirements

For a type to work with RoundTripStringJsonConverter, it must meet these requirements:

  1. Have a public static method with one of the supported names (FromString, Parse, Create, or Convert)
  2. The method must take a single string parameter
  3. The method must return an instance of the declaring type
  4. Override ToString() to provide a string representation that can be reversed by the conversion method
Valid Method Signatures
// All of these are valid conversion methods:
public static MyType FromString(string value) { ... }
public static MyType Parse(string value) { ... }
public static MyType Create(string value) { ... }
public static MyType Convert(string value) { ... }
Invalid Method Signatures
// These will NOT work:
public MyType FromString(string value) { ... }        // Not static
public static MyType FromString(int value) { ... }    // Wrong parameter type
public static string FromString(string value) { ... } // Wrong return type
public static MyType FromString(string value, IFormatProvider provider) { ... } // Too many parameters

Performance Considerations

  • Reflection Caching: Method information is cached for improved performance on repeated conversions
  • Large Collections: Tested with collections of 1000+ items
  • Memory Efficiency: Minimal memory overhead per conversion
  • Thread Safety: The converter factory is thread-safe

Error Handling

The converter provides comprehensive error handling:

  • Invalid JSON Types: Throws JsonException for non-string JSON tokens
  • Conversion Failures: Propagates exceptions from conversion methods
  • Missing Methods: Types without valid conversion methods are ignored
  • Null Arguments: Proper ArgumentNullException handling

Migration from ToStringJsonConverter

If you're migrating from the previous ToStringJsonConverter:

  1. Update package reference to ktsu.RoundTripStringJsonConverter
  2. Update using statements: using ktsu.RoundTripStringJsonConverter;
  3. Update converter instantiation: new RoundTripStringJsonConverterFactory()
  4. Your existing FromString methods will continue to work unchanged
  5. You can now also use Parse, Create, or Convert methods

Contributing

Contributions are welcome! Here's how you can help:

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Please make sure to update tests as appropriate.

License

This project is licensed under the MIT License - see the LICENSE.md file for details.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on ktsu.RoundTripStringJsonConverter:

Package Downloads
ktsu.AppDataStorage

Application data management library using JSON serialization to save and load data in the user's app data folder.

ktsu.AppData

Application data storage library for .NET that provides type-safe persistence with dependency injection support. Features automatic backup and recovery, debounced saves, mock file system support for testing, and cross-platform storage using the user's app data directory.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.3 243 8/25/2025
1.0.2 212 6/16/2025
1.0.1 148 6/16/2025
1.0.1-pre.2 121 6/16/2025
1.0.1-pre.1 150 6/14/2025
1.0.0 251 6/13/2025

## v1.0.2 (patch)

Changes since v1.0.1:

- Update copyright notice and enhance winget manifest script ([@matt-edmondson](https://github.com/matt-edmondson))
## v1.0.1 (patch)

Changes since v1.0.0:

- [patch] Force a patch ([@matt-edmondson](https://github.com/matt-edmondson))
## v1.0.1-pre.2 (prerelease)

Changes since v1.0.1-pre.1:
## v1.0.1-pre.1 (prerelease)

Incremental prerelease update.
## v1.0.0 (major)

- Refactor test method names to camel case ([@matt-edmondson](https://github.com/matt-edmondson))
- Enhance RoundTripStringJsonConverter to support multiple string conversion methods ([@matt-edmondson](https://github.com/matt-edmondson))
- Renamed metadata files ([@matt-edmondson](https://github.com/matt-edmondson))
- Refactor test files to improve code organization and consistency ([@matt-edmondson](https://github.com/matt-edmondson))
- Add scripts for automated metadata generation and versioning ([@matt-edmondson](https://github.com/matt-edmondson))
- Add null check in TestRoundTrip to prevent null exception ([@matt-edmondson](https://github.com/matt-edmondson))
- Update README with comprehensive documentation and usage examples ([@matt-edmondson](https://github.com/matt-edmondson))
- 1.0.0 ([@matt-edmondson](https://github.com/matt-edmondson))
- Refactor test classes to utilize primary constructor syntax for string types ([@matt-edmondson](https://github.com/matt-edmondson))
- Add documentation comments ([@matt-edmondson](https://github.com/matt-edmondson))
- Refactor and enhance testing suite for RoundTripStringJsonConverter ([@matt-edmondson](https://github.com/matt-edmondson))
- Rename package to ktsu.ToStringJsonConverter and update ktsu.Extensions to version 1.0.30 ([@matt-edmondson](https://github.com/matt-edmondson))
- Update Extensions package, and project version ([@matt-edmondson](https://github.com/matt-edmondson))
- Fix compilation errors and warnings in test suite for RoundTripStringJsonConverter ([@matt-edmondson](https://github.com/matt-edmondson))
- Add SpecStory configuration files and rename library to RoundTripStringJsonConverter ([@matt-edmondson](https://github.com/matt-edmondson))
- Apply new editorconfig ([@matt-edmondson](https://github.com/matt-edmondson))
- Update LICENSE file to LICENSE.md with copyright notice ([@matt-edmondson](https://github.com/matt-edmondson))
- Refactor DESCRIPTION and update project SDK references to ktsu.Sdk.Lib and ktsu.Sdk.Test ([@matt-edmondson](https://github.com/matt-edmondson))
- Update packages ([@matt-edmondson](https://github.com/matt-edmondson))
- Update ktsu.Extensions package reference to version 1.5.5 ([@matt-edmondson](https://github.com/matt-edmondson))
- Migrate ktsu.io to ktsu namespace ([@matt-edmondson](https://github.com/matt-edmondson))
- Add project files. ([@matt-edmondson](https://github.com/matt-edmondson))
- Add new SpecStory history file for untitled entry on 2025-06-13 ([@matt-edmondson](https://github.com/matt-edmondson))
- Suppress specific warnings in csproj ([@matt-edmondson](https://github.com/matt-edmondson))
- Update ktsu.Extensions package reference to version 1.0.31 ([@matt-edmondson](https://github.com/matt-edmondson))
- Migrate ktsu.io to ktsu namespace ([@matt-edmondson](https://github.com/matt-edmondson))
- Update documentation and changelog for RoundTripStringJsonConverter ([@matt-edmondson](https://github.com/matt-edmondson))
- Remove Directory.Build.props and Directory.Build.targets files; add copyright headers to ToStringJsonConverter and test files. ([@matt-edmondson](https://github.com/matt-edmondson))
- Add mailmap ([@matt-edmondson](https://github.com/matt-edmondson))
- Replace LICENSE file with LICENSE.md and update copyright information ([@matt-edmondson](https://github.com/matt-edmondson))
- Enhance RoundTripStringJsonConverter and fix collection handling in tests ([@matt-edmondson](https://github.com/matt-edmondson))
- Add LICENSE template ([@matt-edmondson](https://github.com/matt-edmondson))