Skip to content

Commit 2c270ee

Browse files
Merge pull request #58 from contentstack/enh/dx-6423
Migrated to newtonsoft.json to System.Text.Json and .NET 10.x support
2 parents dff907e + b1dbc4d commit 2c270ee

19 files changed

Lines changed: 489 additions & 229 deletions

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
### Version: 2.0.0-beta.1
2+
#### Date: April-27-2026
3+
- **Breaking:** Replaced **Newtonsoft.Json** with **System.Text.Json** across the package. The `Newtonsoft.Json` package reference is removed; add `System.Text.Json` (or rely on the BCL on supported runtimes) as needed in consuming projects.
4+
- **Breaking:** Variant metadata APIs that previously took `JObject` / `JArray` now use `System.Text.Json.Nodes.JsonObject` and `JsonArray` (`GetVariantAliases`, `GetVariantMetadataTags`, and obsolete `GetDataCsvariantsAttribute` overloads).
5+
- JSON serialization uses the same model attributes with `System.Text.Json.Serialization` (`JsonPropertyName`, `JsonConverter`), including custom converters for RTE/GQL-shaped JSON and **path-mapped** embedded models (`PathMappedJsonConverter<T>`).
6+
- RTE JSON deserialization tolerates **trailing commas** when using the documented test/helper patterns (`AllowTrailingCommas`); attribute dictionaries may surface **`JsonElement`** values instead of boxed strings—use helpers or unwrap explicitly if you access `Node.attrs` directly.
7+
- Internal: `LangVersion` set to **latest** for multi-target builds; utilities normalize attribute values where the HTML pipeline expects strings.
8+
19
### Version: 1.2.0
210
#### Date: March-31-2026
311
- Added `GetVariantMetadataTags(JObject, string)` and `GetVariantMetadataTags(JArray, string)` as the canonical API for building the `data-csvariants` payload (same behavior as the previous helpers).

Contentstack.Utils.Tests/Contentstack.Utils.Tests.csproj

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>net7.0</TargetFrameworks>
4+
<TargetFrameworks>net10.0</TargetFrameworks>
55

66
<IsPackable>false</IsPackable>
77
<ReleaseVersion>$(Version)</ReleaseVersion>
88
</PropertyGroup>
99

1010
<ItemGroup>
1111
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
12-
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
1312
<PackageReference Include="coverlet.collector" Version="6.0.4">
1413
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
1514
<PrivateAssets>all</PrivateAssets>

Contentstack.Utils.Tests/DefaultRenderTest.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Contentstack.Utils.Tests.Helpers;
66
using Contentstack.Utils.Tests.Constants;
77
using System;
8+
using Contentstack.Utils;
89

910
namespace Contentstack.Utils.Tests
1011
{
@@ -178,9 +179,9 @@ public void testLinkhDocument()
178179

179180
string result = defaultRender.RenderNode("a", nodeLink, (nodes) => { return text; });
180181

181-
string url = nodeLink.attrs.ContainsKey("url") ? (string)nodeLink.attrs["url"] : "";
182-
string target = nodeLink.attrs.ContainsKey("target") ? (string)nodeLink.attrs["target"] : "";
183-
string title = nodeLink.attrs.ContainsKey("title") ? (string)nodeLink.attrs["title"] : "";
182+
string url = nodeLink.attrs.ContainsKey("url") ? JsonAttrValue.AsString(nodeLink.attrs["url"]) : "";
183+
string target = nodeLink.attrs.ContainsKey("target") ? JsonAttrValue.AsString(nodeLink.attrs["target"]) : "";
184+
string title = nodeLink.attrs.ContainsKey("title") ? JsonAttrValue.AsString(nodeLink.attrs["title"]) : "";
184185

185186
Assert.Equal($"<a href=\"{url}\" target=\"{target}\" title=\"{title}\" >Text To set Link</a>", result);
186187
}

Contentstack.Utils.Tests/Helpers/NodeParser.cs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,35 @@
1-
using Contentstack.Utils.Interfaces;
1+
using System.Text.Json;
2+
using Contentstack.Utils.Interfaces;
23
using Contentstack.Utils.Models;
34
using Contentstack.Utils.Tests.Constants;
45
using Contentstack.Utils.Tests.Mocks;
5-
using Newtonsoft.Json;
66

77
namespace Contentstack.Utils.Tests.Helpers
88
{
99
public class NodeParser
1010
{
11-
public static Node parse(string jsonNode)
11+
private static readonly JsonSerializerOptions SerializerSettings = new JsonSerializerOptions
1212
{
13-
JsonSerializerSettings SerializerSettings = new JsonSerializerSettings();
14-
JsonSerializer Serializer = JsonSerializer.Create(SerializerSettings);
13+
AllowTrailingCommas = true,
14+
};
1515

16-
return JsonConvert.DeserializeObject<Node>(jsonNode, SerializerSettings);
16+
public static Node parse(string jsonNode)
17+
{
18+
return JsonSerializer.Deserialize<Node>(jsonNode, SerializerSettings);
1719
}
1820
}
21+
1922
public class GQLParser
2023
{
21-
public static GQLModel<T> parse<T>(string jsonNode, string embedConnection = null) where T: IEmbeddedObject
24+
private static readonly JsonSerializerOptions SerializerSettings = new JsonSerializerOptions
25+
{
26+
AllowTrailingCommas = true,
27+
};
28+
29+
public static GQLModel<T> parse<T>(string jsonNode, string embedConnection = null) where T : IEmbeddedObject
2230
{
2331
var data = JsonToHtmlConstants.KGQLModel(jsonNode, embedConnection);
24-
JsonSerializerSettings SerializerSettings = new JsonSerializerSettings();
25-
JsonSerializer Serializer = JsonSerializer.Create(SerializerSettings);
26-
return JsonConvert.DeserializeObject<GQLModel<T>>(data, SerializerSettings);
32+
return JsonSerializer.Deserialize<GQLModel<T>>(data, SerializerSettings);
2733
}
2834
}
29-
3035
}
31-

Contentstack.Utils.Tests/Mocks/CustomRenderOptionMock.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Collections.Generic;
2+
using Contentstack.Utils;
23
using Contentstack.Utils.Interfaces;
34
using Contentstack.Utils.Models;
45
using HtmlAgilityPack;
@@ -17,9 +18,9 @@ public override string RenderNode(string nodeType, Node node, NodeChildrenCallBa
1718
case "a":
1819
if (node.attrs.ContainsKey("target"))
1920
{
20-
return $"<a href=\"{(string)node.attrs["url"]}\" target=\"{(string)node.attrs["target"]}\">{callBack(node.children)}</a>";
21+
return $"<a href=\"{JsonAttrValue.AsString(node.attrs["url"])}\" target=\"{JsonAttrValue.AsString(node.attrs["target"])}\">{callBack(node.children)}</a>";
2122
}
22-
return $"<a href=\"{(string)node.attrs["url"]}\">{callBack(node.children)}</a>";
23+
return $"<a href=\"{JsonAttrValue.AsString(node.attrs["url"])}\">{callBack(node.children)}</a>";
2324
}
2425
return base.RenderNode(nodeType, node, callBack);
2526
}

Contentstack.Utils.Tests/Mocks/GQLModel.cs

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,73 +2,71 @@
22
using Contentstack.Utils.Converters;
33
using Contentstack.Utils.Interfaces;
44
using Contentstack.Utils.Models;
5-
using Newtonsoft.Json;
5+
using System.Text.Json.Serialization;
66

77
namespace Contentstack.Utils.Tests.Mocks
88
{
9-
public class GQLModel<T> where T: IEmbeddedObject
9+
public class GQLModel<T> where T : IEmbeddedObject
1010
{
11-
[Newtonsoft.Json.JsonConverter(typeof(RTEJsonConverter))]
1211
public JsonRTENodes<T> multiplerte { get; set; }
1312
public JsonRTENode<T> singlerte { get; set; }
1413
}
1514

16-
[Newtonsoft.Json.JsonConverter(typeof(RTEJsonConverter))]
15+
[JsonConverter(typeof(PathMappedJsonConverter<EntryModel>))]
1716
public class EntryModel : IEmbeddedEntry
1817
{
19-
[JsonProperty("system.uid")]
18+
[JsonPropertyName("system.uid")]
2019
public string Uid
2120
{
2221
get;
2322
set;
2423
}
25-
[JsonProperty("system.content_type_uid")]
24+
[JsonPropertyName("system.content_type_uid")]
2625
public string ContentTypeUid
2726
{
2827
get;
2928
set;
3029
}
31-
[JsonProperty("title")]
30+
[JsonPropertyName("title")]
3231
public string Title
3332
{
3433
get;
3534
set;
3635
}
3736
}
3837

39-
[Newtonsoft.Json.JsonConverter(typeof(RTEJsonConverter))]
38+
[JsonConverter(typeof(PathMappedJsonConverter<AssetModel>))]
4039
public class AssetModel : IEmbeddedAsset
4140
{
42-
[JsonProperty("system.uid")]
41+
[JsonPropertyName("system.uid")]
4342
public string Uid
4443
{
4544
get;
4645
set;
4746
}
48-
[JsonProperty("system.content_type_uid")]
47+
[JsonPropertyName("system.content_type_uid")]
4948
public string ContentTypeUid
5049
{
5150
get;
5251
set;
5352
}
54-
[JsonProperty("title")]
53+
[JsonPropertyName("title")]
5554
public string Title
5655
{
5756
get;
5857
set;
5958
}
60-
[JsonProperty("filename")]
59+
[JsonPropertyName("filename")]
6160
public string FileName
6261
{
6362
get;
6463
set;
6564
}
66-
[JsonProperty("url")]
65+
[JsonPropertyName("url")]
6766
public string Url
6867
{
6968
get;
7069
set;
7170
}
7271
}
7372
}
74-

0 commit comments

Comments
 (0)