TinyString 0.3.0
dotnet add package TinyString --version 0.3.0
NuGet\Install-Package TinyString -Version 0.3.0
<PackageReference Include="TinyString" Version="0.3.0" />
<PackageVersion Include="TinyString" Version="0.3.0" />
<PackageReference Include="TinyString" />
paket add TinyString --version 0.3.0
#r "nuget: TinyString, 0.3.0"
#:package TinyString@0.3.0
#addin nuget:?package=TinyString&version=0.3.0
#tool nuget:?package=TinyString&version=0.3.0
TinyString
![]()
Turn any .NET object into a readable string. Zero config for simple cases, a clean fluent API when you want more.
dotnet add package TinyString
Zero config
Call .Stringify() on anything:
using TinyString;
var book = new Book { Title = "1984", Author = "George Orwell", Pages = 328 };
book.Stringify();
// β "Book. Title: 1984, Author: George Orwell, Pages: 328"
All public properties, declaration order, class name as header, floats at 2 decimal places. No setup required.
Fluent API
Pass a configuration action when you need more control. Everything lives at the call site β your classes stay clean:
zoo.Stringify(o => o
.MultiLine()
.Label("π¦ Zoo")
.For(x => x.EntrancePrice).Prefix("$").Decimals(0));
π¦ Zoo
Name: Woodland Zoo
EntrancePrice: $15
Animals:
|_ Animal. Name: Mittens, Species: Cat, Weight: 4.50
|_ Animal. Name: Tony, Species: Tiger, Weight: 120.30
In multi-line mode, collections are automatically rendered with |_ per item. In single-line mode they're joined with ", ". No extra configuration needed.
Options
Global
| Method | What it does | Default |
|---|---|---|
.MultiLine() / .SingleLine() |
Layout style | single-line |
.Label("β¦") |
Replace the class name header | class name |
.NoLabel() |
Hide the header entirely | β |
.Separator("β¦") |
Between properties in single-line | ", " |
.CollectionSeparator("β¦") |
Override the auto collection separator | auto |
.Decimals(n) |
Decimal places for floats | 2 |
.Keys(NamingFormat.X) |
Key naming style | PascalCase |
.NullAs("β¦") |
Token used for null values | "null" |
.Only(x => x.A, x => x.B) |
Whitelist β show only these properties | all |
Collection items are rendered based on the active style: joined with ", " in single-line, or on their own line prefixed with |_ in multi-line. Multi-line items are indented to align under the prefix, so nested structures stay readable at any depth.
Available naming formats: PascalCase, CamelCase, SnakeCase, KebabCase, HumanCase.
Per property
Chain .For(x => x.Prop) to configure a specific property, then keep chaining .For() to move to the next one:
animal.Stringify(o => o
.NoLabel()
.Separator(" ")
.For(x => x.Name).NoKey()
.For(x => x.Species).Prefix("(").Suffix(")").NoKey()
.For(x => x.Weight).NoKey().Suffix("kg").Decimals(2)
.For(x => x.Age).NoKey().Suffix("yrs")
.For(x => x.IsRare).Ignore());
// β "Mittens (Cat) 4.50kg 5yrs"
| Method | What it does |
|---|---|
.Ignore() |
Exclude this property |
.As("β¦") |
Rename the key |
.NoKey() |
Show only the value |
.Prefix("β¦") / .Suffix("β¦") |
Wrap the value |
.Separator("β¦") |
Collection separator for this property |
.Decimals(n) |
Decimal places for this property |
.MaxItems(n) |
Truncate a collection; appends "... and N more" |
.When(v => β¦) |
Show only when the predicate is true |
.ValueFormat(v => β¦) |
Full control over value rendering |
.ReplaceValues(dict) |
Swap specific values for custom strings |
.DateFormat("β¦") |
Format DateTime / DateTimeOffset values |
.BoolAs("Yes", "No") |
Custom labels for true / false |
.Truncate(n) |
Cap string length, appends "β¦" |
.Transform(v => β¦) |
Transform the value before rendering |
.UpperCase() / .LowerCase() |
Case conversion shortcuts |
.NullAs("β¦") |
Per-property null token (overrides global) |
.NumberFormat("β¦") |
.NET format string for numeric values |
.Highlight(pred, fmt) |
Conditional formatting when predicate matches |
.Only() is the shorthand for whitelisting a few properties without chaining multiple .Ignore() calls:
animal.Stringify(o => o.Only(x => x.Name, x => x.Species));
// β "Animal. Name: Mittens, Species: Cat"
Value formatting
ReplaceValues β swap specific values for labels or emoji
Map known values to display strings. Works with any type β strings, ints, enums, etc. Values not in the dictionary render normally.
Matching is done against the rendered string representation, so for complex types (classes), the replacement matches against ToString().
task.Stringify(o => o
.For(x => x.Source).ReplaceValues(new() {
{ "area", "πΊοΈ" },
{ "inbox", "π₯" }
})
.For(x => x.Priority).ReplaceValues(new() {
{ 1, "π΄ Critical" },
{ 2, "π‘ Medium" },
{ 3, "π’ Low" }
}));
// β "Task. Title: Fix bug, Source: π₯, Priority: π΄ Critical"
For nested objects with ToString() overrides:
// Given: AnimalWithToString.ToString() β "Mittens (Cat)"
task.Stringify(o => o
.For(x => x.Owner).ReplaceValues(new() {
{ new Animal { Name = "Mittens", Species = "Cat" }, "π± Mittens" }
}));
// β "Task. Title: Fix bug, Owner: π± Mittens"
DateFormat β format dates and times
Apply a .NET format string to DateTime or DateTimeOffset properties.
event.Stringify(o => o
.For(x => x.StartsAt).DateFormat("yyyy-MM-dd")
.For(x => x.CreatedAt).DateFormat("dd MMM yyyy HH:mm"));
// β "Event. Name: Launch, StartsAt: 2026-03-15, CreatedAt: 01 Jun 2026 09:00"
BoolAs β friendly true/false labels
Replace True / False with any pair of strings.
animal.Stringify(o => o
.For(x => x.IsRare).BoolAs("β
", "β"));
// β "Animal. Name: Mittens, ..., IsRare: β"
user.Stringify(o => o
.For(x => x.IsActive).BoolAs("Yes", "No"));
// β "User. Name: Alice, IsActive: Yes"
Truncate β cap long strings
Cut values longer than n characters and append β¦.
article.Stringify(o => o
.For(x => x.Body).Truncate(50));
// β "Article. Title: Hello, Body: Lorem ipsum dolor sit amet, consectetur adipisciβ¦"
Transform / UpperCase / LowerCase
Transform the value before it goes through normal rendering. The result is then converted to a string using the standard rules.
animal.Stringify(o => o
.For(x => x.Name).UpperCase()
.For(x => x.Species).LowerCase());
// β "Animal. Name: MITTENS, Species: cat, ..."
// Custom transform β any function that returns a new value:
order.Stringify(o => o
.For(x => x.Tags).Transform(tags => string.Join(", ", tags.Select(t => $"#{t}"))));
Per-property NullAs
Override the global null token for a single property.
sparse.Stringify(o => o
.NullAs("β") // global default
.For(x => x.Name).NullAs("N/A")); // just for Name
// β "Sparse. Name: N/A, Description: β, Count: 3"
NumberFormat β .NET numeric format strings
Use any standard or custom .NET numeric format: "N0" for thousands separators, "P1" for percentage, "C" for currency, "D6" for zero-padded integers, etc.
invoice.Stringify(o => o
.For(x => x.Amount).NumberFormat("N2")
.For(x => x.TaxRate).NumberFormat("P0")
.For(x => x.Id).NumberFormat("D6"));
// β "Invoice. Id: 001234, Amount: 12,345.68, TaxRate: 21 %"
Highlight β conditional formatting
Apply a custom formatter only when a condition is met. Values that don't match the predicate render normally.
invoice.Stringify(o => o
.For(x => x.Amount).Highlight(
v => v > 100,
v => $"β οΈ {v:F0}"));
// amount = 150 β "Amount: β οΈ 150"
// amount = 50 β "Amount: 50.00"
Combining features
All per-property features compose naturally:
task.Stringify(o => o
.For(x => x.Source)
.ReplaceValues(new() { { "inbox", "Inbox" } })
.Prefix("[").Suffix("]"))
.For(x => x.Title).UpperCase().Truncate(20));
// β "Task. Title: FIX THE CRITICAL BUβ¦, Source: [Inbox], Priority: 1"
Nested objects
Nested objects are rendered using the first match in this priority order:
- A
ForNested<T>()configuration registered on the parent - An overridden
ToString()on the nested type - Reflection over public properties (same defaults as zero-config)
var order = new Order { Product = new Product { Name = "Book", Price = 12.99 }, Qty = 2 };
order.Stringify();
// β "Order. Product: Product. Name: Book, Price: 12.99, Qty: 2"
ForNested
Configure a nested type directly from the root call. The configuration applies wherever that type appears β as a property or inside a collection:
zoo.Stringify(o => o
.MultiLine()
.ForNested<Animal>(a => a
.NoLabel()
.Separator(" ")
.For(x => x.Name).NoKey()
.For(x => x.Species).Prefix("(").Suffix(")").NoKey()
.For(x => x.Weight).NoKey().Suffix("kg"))
.For(x => x.EntrancePrice).Prefix("$").Decimals(0));
Zoo
EntrancePrice: $15
Animals:
|_ Mittens (Cat) 4.50kg
|_ Tony (Tiger) 120.30kg
ToString()
If a nested type overrides ToString(), that is used automatically. If ToString() calls Stringify(), it recurses:
public class Animal
{
public string Name { get; set; }
public string Species { get; set; }
public override string ToString() => this.Stringify(o => o
.NoLabel()
.For(x => x.Name).NoKey()
.For(x => x.Species).Prefix("(").Suffix(")").NoKey());
// β "Mittens (Cat)"
}
Migrating from the attribute API
Previous versions configured stringification via [Stringify], [StringifyProperty], and [StringifyIgnore] attributes. These still work but are deprecated and will be removed in a future major version. Move the configuration to the .Stringify() call site instead.
MIT License
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. 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. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.