Skip to content

Commit 7fe2bd2

Browse files
committed
Json
feat: json helpers added
1 parent 6453756 commit 7fe2bd2

File tree

8 files changed

+374
-4
lines changed

8 files changed

+374
-4
lines changed

Core.Json/Json.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ namespace KY.Core;
77

88
public static class Json
99
{
10+
public static JsonArray Array { get; } = new();
11+
public static JsonObject Object { get; } = new();
12+
1013
public static T Deserialize<T>(string path)
1114
{
1215
if (!FileSystem.FileExists(path))

Core.Json/JsonArray.cs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
using System;
2+
using System.Linq;
3+
using Newtonsoft.Json.Linq;
4+
5+
namespace KY.Core;
6+
7+
public class JsonArray
8+
{
9+
public void Add<T>(JToken target, string propertyPath, T value)
10+
{
11+
if (value is JToken token)
12+
{
13+
this.Add(target, propertyPath, token);
14+
}
15+
else
16+
{
17+
this.Add(target, propertyPath, new JValue(value));
18+
}
19+
}
20+
21+
public void Add(JToken target, string propertyPath, JToken value)
22+
{
23+
if (target.SelectToken(propertyPath) is not JArray array)
24+
{
25+
throw new InvalidOperationException($"The property {propertyPath} is not an array");
26+
}
27+
array.Add(value);
28+
}
29+
30+
public void Insert<T>(JToken target, string propertyPath, int index, T value)
31+
{
32+
if (value is JToken token)
33+
{
34+
this.Insert(target, propertyPath, index, token);
35+
}
36+
else
37+
{
38+
this.Insert(target, propertyPath, index, new JValue(value));
39+
}
40+
}
41+
42+
public void Insert(JToken target, string propertyPath, int index, JToken value)
43+
{
44+
if (target.SelectToken(propertyPath) is not JArray array)
45+
{
46+
throw new InvalidOperationException($"The property {propertyPath} is not an array");
47+
}
48+
array.Insert(index, value);
49+
}
50+
51+
public void Remove<T>(JToken target, string propertyPath, T value)
52+
{
53+
if (value is JToken token)
54+
{
55+
this.Remove(target, propertyPath, token);
56+
}
57+
else
58+
{
59+
this.Remove(target, propertyPath, new JValue(value));
60+
}
61+
}
62+
63+
public void Remove(JToken target, string propertyPath, JToken value)
64+
{
65+
if (target.SelectToken(propertyPath) is not JArray array)
66+
{
67+
throw new InvalidOperationException($"The property {propertyPath} is not an array");
68+
}
69+
if (array.Contains(value))
70+
{
71+
array.Remove(value);
72+
}
73+
else
74+
{
75+
array.Remove(array.First(x => x.ToString() == value.ToString()));
76+
}
77+
}
78+
}

Core.Json/JsonObject.cs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
using System;
2+
using System.Linq;
3+
using Newtonsoft.Json.Linq;
4+
5+
namespace KY.Core;
6+
7+
public class JsonObject
8+
{
9+
public void Set<T>(JToken target, string propertyPath, T value)
10+
{
11+
if (value is JToken token)
12+
{
13+
this.Set(target, propertyPath, token);
14+
}
15+
else
16+
{
17+
this.Set(target, propertyPath, (JToken)new JValue(value));
18+
}
19+
}
20+
21+
public void Set(JToken target, string propertyPath, JToken value)
22+
{
23+
(string objectPath, string propertyName) = this.GetProperty(propertyPath);
24+
JToken token = string.IsNullOrEmpty(objectPath) ? target : target.SelectToken(objectPath);
25+
if (token is not JObject obj)
26+
{
27+
throw new InvalidOperationException($"The property {objectPath} is not an object");
28+
}
29+
obj[propertyName] = value;
30+
}
31+
32+
public void SetFirst<T>(JToken target, string propertyPath, T value)
33+
{
34+
if (value is JToken token)
35+
{
36+
this.SetFirst(target, propertyPath, token);
37+
}
38+
else
39+
{
40+
this.SetFirst(target, propertyPath, (JToken)new JValue(value));
41+
}
42+
}
43+
44+
public void SetFirst(JToken target, string propertyPath, JToken value)
45+
{
46+
(string objectPath, string propertyName) = this.GetProperty(propertyPath);
47+
JToken token = string.IsNullOrEmpty(objectPath) ? target : target.SelectToken(objectPath);
48+
if (token is not JObject obj)
49+
{
50+
throw new InvalidOperationException($"The property {objectPath} is not an object");
51+
}
52+
if (obj.ContainsKey(propertyName))
53+
{
54+
obj[propertyName] = value;
55+
}
56+
else
57+
{
58+
obj.AddFirst(new JProperty(propertyName, value));
59+
}
60+
}
61+
62+
public void SetAfter<T>(JToken target, string propertyPath, string afterProperty, T value)
63+
{
64+
if (value is JToken token)
65+
{
66+
this.SetAfter(target, propertyPath, afterProperty, token);
67+
}
68+
else
69+
{
70+
this.SetAfter(target, propertyPath, afterProperty, (JToken)new JValue(value));
71+
}
72+
}
73+
74+
public void SetAfter(JToken target, string propertyPath, string afterProperty, JToken value)
75+
{
76+
(string objectPath, string propertyName) = this.GetProperty(propertyPath);
77+
JToken token = string.IsNullOrEmpty(objectPath) ? target : target.SelectToken(objectPath);
78+
if (token is not JObject obj)
79+
{
80+
throw new InvalidOperationException($"The property {objectPath} is not an object");
81+
}
82+
if (obj.ContainsKey(propertyName) || !obj.ContainsKey(afterProperty))
83+
{
84+
obj[propertyName] = value;
85+
}
86+
else
87+
{
88+
obj[afterProperty]?.Parent?.AddAfterSelf(new JProperty(propertyName, value));
89+
}
90+
}
91+
92+
public void Remove(JToken target, string propertyPath)
93+
{
94+
(string objectPath, string propertyName) = this.GetProperty(propertyPath);
95+
JToken token = string.IsNullOrEmpty(objectPath) ? target : target.SelectToken(objectPath);
96+
if (token is not JObject obj)
97+
{
98+
throw new InvalidOperationException($"The property {objectPath} is not an object");
99+
}
100+
obj.Remove(propertyName);
101+
}
102+
103+
private Tuple<string, string> GetProperty(string propertyPath)
104+
{
105+
string[] chunks = propertyPath.Split('.');
106+
return new Tuple<string, string>(string.Join(".", chunks.Take(chunks.Length - 1)), chunks.Last());
107+
}
108+
}

Core.Json/KY.Core.Json.csproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
<PropertyGroup>
44
<TargetFramework>netstandard2.0</TargetFramework>
55
<RootNamespace>KY.Core</RootNamespace>
6-
<Version>4.2.1</Version>
6+
<Version>4.3.0</Version>
77
<Authors>KY-Programming</Authors>
88
<Company>KY-Programmingp</Company>
99
<Product>KY.Core</Product>
10-
<Copyright>2022 - KY-Programming</Copyright>
10+
<Copyright>2023 - KY-Programming</Copyright>
1111
<Description>KY.Core.Json for .net Standard
1212
Contains Json serialization and deserialization helpers
1313
</Description>
@@ -21,8 +21,8 @@
2121
</PropertyGroup>
2222

2323
<ItemGroup>
24-
<PackageReference Include="KY.Core.Common" Version="4.30.1" />
25-
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
24+
<PackageReference Include="KY.Core.Common" Version="4.30.1"/>
25+
<PackageReference Include="Newtonsoft.Json" Version="13.0.1"/>
2626
</ItemGroup>
2727

2828
</Project>

KY.Core.Json.Tests/GlobalUsings.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
global using Microsoft.VisualStudio.TestTools.UnitTesting;

KY.Core.Json.Tests/JsonArrayTests.cs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
using Newtonsoft.Json;
2+
using Newtonsoft.Json.Linq;
3+
4+
namespace KY.Core.Tests;
5+
6+
[TestClass]
7+
public class JsonArrayTests
8+
{
9+
[TestMethod]
10+
public void Add_a_String_to_an_existing_Array()
11+
{
12+
JObject jObject = JsonConvert.DeserializeObject<JObject>("""
13+
{
14+
"name": "John Doe",
15+
"age": 42,
16+
"children": [
17+
"John Jr.",
18+
"Jane"
19+
]
20+
}
21+
""")!;
22+
Json.Array.Add(jObject, "children", "Jack");
23+
Assert.AreEqual(3, jObject["children"]?.Count());
24+
Assert.AreEqual("John Jr.", jObject["children"]?[0]);
25+
Assert.AreEqual("Jane", jObject["children"]?[1]);
26+
Assert.AreEqual("Jack", jObject["children"]?[2]);
27+
}
28+
29+
[TestMethod]
30+
public void Add_a_Object_to_an_existing_Array()
31+
{
32+
JObject jObject = JsonConvert.DeserializeObject<JObject>("""
33+
{
34+
"name": "John Doe",
35+
"age": 42,
36+
"children": [
37+
{
38+
"name": "John Jr.",
39+
"age": 13
40+
},
41+
{
42+
"name": "Jane",
43+
"age": 9
44+
}
45+
]
46+
}
47+
""")!;
48+
Json.Array.Add(jObject, "children", JsonConvert.DeserializeObject<JObject>("""
49+
{
50+
"name": "Jack",
51+
"age": 2
52+
}
53+
"""));
54+
Assert.AreEqual(3, jObject["children"]?.Count());
55+
Assert.AreEqual("Jack", jObject["children"]?[2]?["name"]);
56+
}
57+
58+
[TestMethod]
59+
public void Remove_a_String_from_an_existing_Array()
60+
{
61+
JObject jObject = JsonConvert.DeserializeObject<JObject>("""
62+
{
63+
"name": "John Doe",
64+
"age": 42,
65+
"children": [
66+
"John Jr.",
67+
"Jane"
68+
]
69+
}
70+
""")!;
71+
Json.Array.Remove(jObject, "children", "Jane");
72+
Assert.AreEqual(1, jObject["children"]?.Count());
73+
Assert.AreEqual("John Jr.", jObject["children"]?[0]);
74+
}
75+
76+
[TestMethod]
77+
public void Remove_a_String_from_an_existing_Deep_Array()
78+
{
79+
JObject jObject = JsonConvert.DeserializeObject<JObject>("""
80+
{
81+
"jd": {
82+
"name": "John Doe",
83+
"age": 42,
84+
"children": [
85+
"John Jr.",
86+
"Jane"
87+
]
88+
}
89+
}
90+
""")!;
91+
Json.Array.Remove(jObject, "jd.children", "Jane");
92+
Assert.AreEqual(1, jObject["jd"]?["children"]?.Count());
93+
Assert.AreEqual("John Jr.", jObject["jd"]?["children"]?[0]);
94+
}
95+
}

KY.Core.Json.Tests/JsonObjectTests.cs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
using Newtonsoft.Json;
2+
using Newtonsoft.Json.Linq;
3+
4+
namespace KY.Core.Tests;
5+
6+
[TestClass]
7+
public class JsonObjectTests
8+
{
9+
[TestMethod]
10+
public void Set_a_property_of_an_existing_Object()
11+
{
12+
JObject jObject = JsonConvert.DeserializeObject<JObject>("""
13+
{
14+
"name": "John Doe",
15+
"age": 42,
16+
"children": [
17+
"John Jr.",
18+
"Jane"
19+
]
20+
}
21+
""")!;
22+
Json.Object.Set(jObject, "name", "Jack");
23+
Assert.AreEqual("Jack", jObject["name"]);
24+
}
25+
26+
[TestMethod]
27+
public void Set_a_property_of_an_existing_Depp_Object()
28+
{
29+
JObject jObject = JsonConvert.DeserializeObject<JObject>("""
30+
{
31+
"name": "John Doe",
32+
"age": 42,
33+
"children": [
34+
{
35+
"name": "John Jr.",
36+
"age": 13
37+
},
38+
{
39+
"name": "Jane",
40+
"age": 9
41+
}
42+
]
43+
}
44+
""")!;
45+
Json.Object.Set(jObject, "children.[1].name", "Jude");
46+
Assert.AreEqual("Jude", jObject["children"]?[1]?["name"]);
47+
}
48+
49+
[TestMethod]
50+
public void Remove_a_property_of_an_existing_Object()
51+
{
52+
JObject jObject = JsonConvert.DeserializeObject<JObject>("""
53+
{
54+
"name": "John Doe",
55+
"age": 42
56+
}
57+
""")!;
58+
Json.Object.Remove(jObject, "age");
59+
Assert.AreEqual("{\"name\":\"John Doe\"}", jObject.ToString(Formatting.None));
60+
}
61+
}

0 commit comments

Comments
 (0)