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" />
                    
Directory.Packages.props
<PackageReference Include="ObjectPath" />
                    
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 ObjectPath --version 1.2.0
                    
#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
                    
Install as a Cake Addin
#tool nuget:?package=ObjectPath&version=1.2.0
                    
Install as a Cake Tool

ObjectPath

NuGet License

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 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.

Version Downloads Last Updated
1.2.0 139 11/27/2025
1.0.6 5,371 6/5/2024
1.0.5 102 6/5/2024
1.0.4 103 6/5/2024
1.0.3 112 6/5/2024
1.0.2 135 6/5/2024
1.0.1 110 6/4/2024