ObjectPath 1.2.0
dotnet add package ObjectPath --version 1.2.0
NuGet\Install-Package ObjectPath -Version 1.2.0
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="ObjectPath" Version="1.2.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ObjectPath" Version="1.2.0" />
<PackageReference Include="ObjectPath" />
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 ObjectPath --version 1.2.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: ObjectPath, 1.2.0"
#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 ObjectPath@1.2.0
#: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=ObjectPath&version=1.2.0
#tool nuget:?package=ObjectPath&version=1.2.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
ObjectPath
A simple and intuitive library for accessing object values using string path expressions in .NET.
Features
- Access nested properties and fields using dot notation (
Address.City) - Array and list index access using bracket notation (
Items[0]) - JSON element support (
System.Text.Json) - Dictionary support (
IDictionary<string, T>,IDictionary,ExpandoObject) - Generic type conversion (
GetValue<T>) - Non-throwing TryGetValue pattern
- Case-insensitive matching by default
- Property and field caching for performance
- .NET 8.0, 9.0, and 10.0 support
Installation
dotnet add package ObjectPath
Quick Start
using ObjectPathLibrary;
var person = new
{
Name = "John",
Age = 30,
Address = new { City = "New York", Street = "123 Main St" }
};
// Extension method
var city = person.GetValueByPath("Address.City"); // "New York"
// Static method
var name = ObjectPath.GetValue(person, "Name"); // "John"
API Reference
Static Methods
| Method | Description |
|---|---|
GetValue(obj, path, ignoreCase) |
Gets value at path, throws on invalid path |
GetValue<T>(obj, path, ignoreCase) |
Gets value with type conversion |
TryGetValue(obj, path, out value, ignoreCase) |
Non-throwing, returns success bool |
TryGetValue<T>(obj, path, out value, ignoreCase) |
Non-throwing with type conversion |
Extension Methods
| Method | Description |
|---|---|
obj.GetValueByPath(path, ignoreCase) |
Gets value at path |
obj.GetValueByPath<T>(path, ignoreCase) |
Gets value with type conversion |
obj.GetValueByPathOrNull(path, ignoreCase) |
Returns null on invalid path |
obj.TryGetValueByPath(path, out value, ignoreCase) |
Non-throwing pattern |
obj.TryGetValueByPath<T>(path, out value, ignoreCase) |
Non-throwing with type conversion |
Usage Examples
Nested Objects
var obj = new
{
User = new
{
Profile = new { Name = "John", Email = "john@example.com" }
}
};
var email = obj.GetValueByPath("User.Profile.Email"); // "john@example.com"
Arrays and Lists
var obj = new
{
Numbers = new[] { 10, 20, 30 },
Users = new[]
{
new { Name = "John" },
new { Name = "Jane" }
}
};
var first = obj.GetValueByPath("Numbers[0]"); // 10
var jane = obj.GetValueByPath("Users[1].Name"); // "Jane"
JSON Elements
using System.Text.Json;
var json = """
{
"name": "John",
"address": { "city": "New York" },
"tags": ["developer", "designer"]
}
""";
var doc = JsonDocument.Parse(json);
var root = doc.RootElement;
var city = ObjectPath.GetValue(root, "address.city"); // "New York"
var tag = ObjectPath.GetValue(root, "tags[0]"); // "developer"
Dictionaries
// Dictionary<string, object>
var dict = new Dictionary<string, object>
{
["Name"] = "John",
["Address"] = new Dictionary<string, object>
{
["City"] = "New York"
}
};
var city = dict.GetValueByPath("Address.City"); // "New York"
// ExpandoObject
dynamic expando = new ExpandoObject();
expando.Name = "John";
expando.Age = 30;
var name = ObjectPath.GetValue((object)expando, "Name"); // "John"
Generic Type Conversion
var obj = new { Count = 42, Price = "19.99", Active = true };
int count = obj.GetValueByPath<int>("Count"); // 42
decimal price = obj.GetValueByPath<decimal>("Price"); // 19.99m
bool active = obj.GetValueByPath<bool>("Active"); // true
TryGetValue Pattern
var obj = new { Name = "John", Age = 30 };
// Non-throwing access
if (obj.TryGetValueByPath("Name", out var name))
{
Console.WriteLine($"Name: {name}");
}
// With type conversion
if (obj.TryGetValueByPath<int>("Age", out var age))
{
Console.WriteLine($"Age: {age}");
}
// Safe access for missing properties
if (!obj.TryGetValueByPath("Email", out _))
{
Console.WriteLine("Email not found");
}
Case Sensitivity
var obj = new { Name = "John", age = 30 };
// Case-insensitive (default)
var name1 = ObjectPath.GetValue(obj, "name"); // "John"
var name2 = ObjectPath.GetValue(obj, "NAME"); // "John"
// Case-sensitive
var name3 = ObjectPath.GetValue(obj, "Name", ignoreCase: false); // "John"
var age = ObjectPath.GetValue(obj, "age", ignoreCase: false); // 30
// Throws InvalidObjectPathException
ObjectPath.GetValue(obj, "name", ignoreCase: false); // Error!
Error Handling
var obj = new { Name = "John" };
// Option 1: GetValueByPathOrNull
var value = obj.GetValueByPathOrNull("NonExistent"); // null
// Option 2: TryGetValue pattern
if (!obj.TryGetValueByPath("NonExistent", out var result))
{
// Handle missing property
}
// Option 3: Catch exception
try
{
var invalid = obj.GetValueByPath("NonExistent");
}
catch (InvalidObjectPathException ex)
{
// ex.Message contains the full path for debugging
Console.WriteLine(ex.Message);
// "Property or field 'NonExistent' not found in path 'NonExistent'."
}
Supported Types
| Type | Support |
|---|---|
| Anonymous types | ✅ |
| Classes/Records | ✅ |
JsonElement |
✅ |
Dictionary<string, T> |
✅ |
IDictionary (Hashtable, etc.) |
✅ |
ExpandoObject |
✅ |
Arrays (T[]) |
✅ |
List<T> |
✅ |
IList |
✅ |
Path Syntax
| Syntax | Description | Example |
|---|---|---|
. |
Property access | Address.City |
[n] |
Array/list index | Items[0] |
| Combined | Nested access | Users[0].Address.City |
Performance
- Property and field lookups are cached using
ConcurrentDictionary - Reflection is used only on first access per type/property combination
- Subsequent accesses use cached
PropertyInfo/FieldInfo
Requirements
- .NET 8.0 or later
License
This project is licensed under the MIT License - see the LICENSE file for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. 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 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 is compatible. 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.
-
net10.0
- No dependencies.
-
net8.0
- No dependencies.
-
net9.0
- 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.