Skip to content

Commit 8d775c7

Browse files
committed
v1.0.6
1 parent 5995807 commit 8d775c7

5 files changed

Lines changed: 338 additions & 12 deletions

File tree

README.md

Lines changed: 103 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ ObjectPath allows you to access values within objects using string path expressi
1717
### Basic Usage
1818

1919
```csharp
20-
using ObjectPath;
20+
using ObjectPathLibrary;
2121

2222
// Example object
2323
var obj = new
@@ -32,15 +32,15 @@ var obj = new
3232
};
3333

3434
// Access values using path expressions
35-
var name = ObjectPath.GetValue(obj, "Name"); // John
36-
var city = ObjectPath.GetValue(obj, "Address.City"); // New York
35+
var name = obj.GetValueByPath("Name"); // John
36+
var city = obj.GetValueByPath("Address.City"); // New York
3737
```
3838

3939
### JSON Example
4040

4141
```csharp
4242
using System.Text.Json;
43-
using ObjectPath;
43+
using ObjectPathLibrary;
4444

4545
// JSON string
4646
var json = @"
@@ -57,16 +57,16 @@ var jsonDocument = JsonDocument.Parse(json);
5757
var jsonElement = jsonDocument.RootElement;
5858

5959
// Access values using path expressions
60-
var name = ObjectPath.GetValue(jsonElement, "name"); // John
61-
var street = ObjectPath.GetValue(jsonElement, "address.street"); // 123 Main St
60+
var name = jsonElement.GetValueByPath("name"); // John
61+
var street = jsonElement.GetValueByPath("address.street"); // 123 Main St
6262
```
6363

6464
### Array Example
6565

6666
ObjectPath supports accessing array and list elements using index notation.
6767

6868
```csharp
69-
using ObjectPath;
69+
using ObjectPathLibrary;
7070

7171
// Example object with arrays and lists
7272
var obj = new
@@ -80,8 +80,8 @@ var obj = new
8080
};
8181

8282
// Access array elements
83-
var firstNumber = ObjectPath.GetValue(obj, "Numbers[0]"); // 1
84-
var secondPersonName = ObjectPath.GetValue(obj, "People[1].Name"); // Jane
83+
var firstNumber = obj.GetValueByPath("Numbers[0]"); // 1
84+
var secondPersonName = obj.GetValueByPath("People[1].Name"); // Jane
8585
```
8686

8787
### Case Sensitivity
@@ -102,10 +102,104 @@ var age = ObjectPath.GetValue(obj, "age", ignoreCase: false); // 30
102102
var invalid = ObjectPath.GetValue(obj, "name", ignoreCase: false);
103103
```
104104

105+
### Dictionary Access
106+
107+
You can also access values in dictionaries using path expressions.
108+
109+
```csharp
110+
using ObjectPathLibrary;
111+
using Xunit;
112+
113+
[Fact]
114+
public void DictionaryAccessTest()
115+
{
116+
var dic = new Dictionary<string, object>
117+
{
118+
["Name"] = "John",
119+
["Age"] = 30,
120+
["Address"] = new Dictionary<string, object>
121+
{
122+
["City"] = "New York",
123+
["Street"] = "123 Main St"
124+
}
125+
};
126+
127+
// Act
128+
var name = dic.GetValueByPath("Name");
129+
var age = dic.GetValueByPath("Age");
130+
var city = dic.GetValueByPath("Address.City");
131+
var street = dic.GetValueByPath("Address.Street");
132+
133+
var address = dic.GetValueByPath("Address") as IDictionary<string, object>;
134+
var addressExpando = address!.ToExpando();
135+
136+
// Assert
137+
Assert.Equal("John", name);
138+
Assert.Equal(30, age);
139+
Assert.Equal("New York", city);
140+
Assert.Equal("123 Main St", street);
141+
142+
Assert.Equal("New York", address["City"]);
143+
Assert.Equal("123 Main St", address["Street"]);
144+
145+
Assert.Equal("New York", addressExpando?.City);
146+
Assert.Equal("123 Main St", addressExpando?.Street);
147+
}
148+
```
149+
150+
### Handling Exceptions
151+
152+
Use `GetValueByPathOrNull` to safely get values without throwing exceptions.
153+
154+
```csharp
155+
using ObjectPathLibrary;
156+
157+
var obj = new
158+
{
159+
Name = "John",
160+
Address = new
161+
{
162+
City = "New York"
163+
}
164+
};
165+
166+
// Access values using path expressions
167+
var name = obj.GetValueByPathOrNull("Name"); // John
168+
var nonExistent = obj.GetValueByPathOrNull("NonExistentProperty"); // null
169+
```
170+
171+
## ObjectPathExtensions.cs
172+
173+
```csharp
174+
namespace ObjectPathLibrary
175+
{
176+
public static class ObjectPathExtensions
177+
{
178+
public static object? GetValueByPath(this object obj, string path)
179+
{
180+
return ObjectPath.GetValue(obj, path);
181+
}
182+
183+
public static object? GetValueByPathOrNull(this object obj, string path)
184+
{
185+
try
186+
{
187+
return ObjectPath.GetValue(obj, path);
188+
}
189+
catch (Exception)
190+
{
191+
return null;
192+
}
193+
}
194+
}
195+
}
196+
```
197+
105198
## Features
106199

107200
- Access nested properties and fields.
108201
- Supports JSON elements.
109202
- Supports array and list index access.
110203
- Case-insensitive by default, with an option for case sensitivity.
111204
- Handles complex nested structures.
205+
- Provides safe access with `GetValueByPathOrNull`.

src/ObjectPath.Tests/ObjectPathTests.cs

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,5 +542,190 @@ public void GetValue_ReturnsCorrectValue_ForVariousDataTypes()
542542
Assert.Equal("Hello", stringValue);
543543
Assert.True((bool)boolValue);
544544
}
545+
546+
547+
[Fact]
548+
public void DynamicAccessTest()
549+
{
550+
// Arrange
551+
var people = new Person[]
552+
{
553+
new Person
554+
{
555+
Name = "John",
556+
Age = 30,
557+
Address = new Address
558+
{
559+
City = "New York",
560+
Street = "123 Main St"
561+
}
562+
},
563+
new Person
564+
{
565+
Name = "Jane",
566+
Age = 25,
567+
Address = new Address
568+
{
569+
City = "London",
570+
Street = "456 Oxford St"
571+
}
572+
}
573+
};
574+
575+
// Act
576+
var person1 = ObjectPath.GetValue(people, "[0]") as dynamic;
577+
578+
// Assert
579+
Assert.Equal("John", person1.Name);
580+
Assert.Equal(30, person1.Age);
581+
Assert.Equal("New York", person1.Address.City);
582+
}
583+
584+
[Fact]
585+
public void DictionaryAccessTest()
586+
{
587+
var dic = new Dictionary<string, object>
588+
{
589+
["Name"] = "John",
590+
["Age"] = 30,
591+
["Address"] = new Dictionary<string, object>
592+
{
593+
["City"] = "New York",
594+
["Street"] = "123 Main St"
595+
}
596+
};
597+
598+
// Act
599+
var name = ObjectPath.GetValue(dic, "Name");
600+
var age = ObjectPath.GetValue(dic, "Age");
601+
var city = ObjectPath.GetValue(dic, "Address.City");
602+
var street = ObjectPath.GetValue(dic, "Address.Street");
603+
604+
var address = ObjectPath.GetValue(dic, "Address") as IDictionary<string, object>;
605+
var addressExpando = address!.ToExpando();
606+
607+
// Assert
608+
Assert.Equal("John", name);
609+
Assert.Equal(30, age);
610+
Assert.Equal("New York", city);
611+
Assert.Equal("123 Main St", street);
612+
613+
Assert.Equal("New York", address["City"]);
614+
Assert.Equal("123 Main St", address["Street"]);
615+
616+
Assert.Equal("New York", addressExpando?.City);
617+
Assert.Equal("123 Main St", addressExpando?.Street);
618+
}
619+
620+
621+
[Fact]
622+
public void GetValueByPath_ValidPath_ReturnsValue()
623+
{
624+
var obj = new
625+
{
626+
Name = "John",
627+
Age = 30,
628+
Address = new
629+
{
630+
City = "New York",
631+
Street = "123 Main St"
632+
}
633+
};
634+
635+
var name = obj.GetValueByPath("Name");
636+
var city = obj.GetValueByPath("Address.City");
637+
638+
Assert.Equal("John", name);
639+
Assert.Equal("New York", city);
640+
}
641+
642+
[Fact]
643+
public void GetValueByPath_InvalidPath_ThrowsException()
644+
{
645+
var obj = new
646+
{
647+
Name = "John",
648+
Age = 30
649+
};
650+
651+
Assert.Throws<InvalidObjectPathException>(() => obj.GetValueByPath("NonExistentProperty"));
652+
}
653+
654+
[Fact]
655+
public void GetValueByPathOrNull_ValidPath_ReturnsValue()
656+
{
657+
var obj = new
658+
{
659+
Name = "John",
660+
Age = 30,
661+
Address = new
662+
{
663+
City = "New York",
664+
Street = "123 Main St"
665+
}
666+
};
667+
668+
var name = obj.GetValueByPathOrNull("Name");
669+
var city = obj.GetValueByPathOrNull("Address.City");
670+
671+
Assert.Equal("John", name);
672+
Assert.Equal("New York", city);
673+
}
674+
675+
[Fact]
676+
public void GetValueByPathOrNull_InvalidPath_ReturnsNull()
677+
{
678+
var obj = new
679+
{
680+
Name = "John",
681+
Age = 30
682+
};
683+
684+
var value = obj.GetValueByPathOrNull("NonExistentProperty");
685+
686+
Assert.Null(value);
687+
}
688+
689+
[Fact]
690+
public void GetValueByPath_DictionaryAccess_ReturnsValue()
691+
{
692+
var dic = new Dictionary<string, object>
693+
{
694+
["Name"] = "John",
695+
["Age"] = 30,
696+
["Address"] = new Dictionary<string, object>
697+
{
698+
["City"] = "New York",
699+
["Street"] = "123 Main St"
700+
}
701+
};
702+
703+
var name = dic.GetValueByPath("Name");
704+
var city = dic.GetValueByPath("Address.City");
705+
706+
Assert.Equal("John", name);
707+
Assert.Equal("New York", city);
708+
}
709+
710+
[Fact]
711+
public void GetValueByPathOrNull_DictionaryAccess_ReturnsValue()
712+
{
713+
var dic = new Dictionary<string, object>
714+
{
715+
["Name"] = "John",
716+
["Age"] = 30,
717+
["Address"] = new Dictionary<string, object>
718+
{
719+
["City"] = "New York",
720+
["Street"] = "123 Main St"
721+
}
722+
};
723+
724+
var name = dic.GetValueByPathOrNull("Name");
725+
var city = dic.GetValueByPathOrNull("Address.City");
726+
727+
Assert.Equal("John", name);
728+
Assert.Equal("New York", city);
729+
}
545730
}
546731
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System.Dynamic;
2+
3+
namespace ObjectPathLibrary
4+
{
5+
public static class DictionaryExtensions
6+
{
7+
public static dynamic ToExpando(this IDictionary<string, object?> dictionary)
8+
{
9+
var expando = new ExpandoObject();
10+
var expandoDict = (IDictionary<string, object?>)expando!;
11+
12+
foreach (var kvp in dictionary)
13+
{
14+
if (kvp.Value is IDictionary<string, object?> dict)
15+
{
16+
expandoDict.Add(kvp.Key, dict.ToExpando());
17+
}
18+
else
19+
{
20+
expandoDict.Add(kvp.Key, kvp.Value);
21+
}
22+
}
23+
24+
return expando;
25+
}
26+
}
27+
}

src/ObjectPath/ObjectPath.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
using System;
2-
using System.Collections;
1+
using System.Collections;
32
using System.Collections.Concurrent;
4-
using System.Collections.Generic;
53
using System.Reflection;
64
using System.Text.Json;
75

0 commit comments

Comments
 (0)