From 28313d2f97e58d1c0fe5ed9b2e133b21620e9ccf Mon Sep 17 00:00:00 2001 From: Chrison Simtian Date: Sun, 24 May 2026 22:51:19 +1200 Subject: [PATCH] chore(text.json): [Obsolete] remaining Newtonsoft surface + migrate SignPathTasks (#83) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Marks the last Newtonsoft-typed types in Fallout.Utilities.Text.Json [Obsolete] for v11 removal, migrates the only viable internal call site (SignPathTasks), and wraps the rest with #pragma + v11 TODO. [Obsolete] additions: - JObjectExtensions.GetChildren, GetChildren, GetPropertyValueOrNull, GetPropertyValue, GetPropertyValue, GetPropertyStringValue - JsonObjectExtensions.ToJObject (the renamed ObjectExtensions class) - AllWritableContractResolver (internal class) - Base64JsonConverter (zero internal callers) - JsonExtensions.DefaultSerializerSettings (the Newtonsoft settings field) Migrations: - src/Fallout.Common/Tools/SignPath/SignPathTasks.cs — fully migrated to STJ. Lines 75 (.ToJson()) and 152-156 (.GetJson() + JToken.Value()) now use JsonExtensions.DefaultSerializerOptions / .GetJsonObject() / .GetValue<>(). Drops `using Newtonsoft.Json.Linq;` entirely. Pragma suppressions for now (separate workstreams will retire each): - src/Fallout.Common/CI/GitHubActions/GitHubActions.cs:117-118 — PullRequestNumber/ Action use JObjectExtensions on the public JObject GitHubEvent property. The GitHubEvent migration is a public API break, scheduled for v11. - src/Fallout.Tooling/ProcessExtensions.cs:55 — StdToJson delegates to Newtonsoft GetJson; part of the Fallout.Tooling #83 sweep. - tests/Fallout.Common.Tests/SettingsTest.cs:174 — Discord test pins Newtonsoft round-trip. - tests/Fallout.Tooling.Tests/OptionsTest.cs:150 — pins Options.JsonSerializerSettings round-trip. - tests/Fallout.Tooling.Tests/ToolOptionsArgumentsTest.cs:194 — uses ToJObject which writes into JObject-typed InternalOptions. - tests/Fallout.Utilities.Tests/Text/SerializationTest.cs:23-24 — pins Newtonsoft serialization round-trip. Shim project (src/Shims/Nuke.Common/Nuke.Common.csproj) adds CS0618 to NoWarn: the TransitionShimGenerator auto-emits delegations to canonical methods and propagates [Obsolete] warnings into those auto-generated shim bodies. Consumers calling the canonical type directly still see [Obsolete] guidance; this NoWarn keeps the shim project's build clean. Propagating [Obsolete] through the generator is a v11 follow-up. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../CI/GitHubActions/GitHubActions.cs | 2 ++ src/Fallout.Common/Tools/SignPath/SignPathTasks.cs | 14 +++++++------- src/Fallout.Tooling/ProcessExtensions.cs | 2 ++ .../AllWritableContractResolver.cs | 1 + .../Base64JsonConverter.cs | 1 + .../JObject.GetChildren.cs | 7 +++++++ .../JObject.GetPropertyValue.cs | 8 ++++++++ src/Fallout.Utilities.Text.Json/JsonExtensions.cs | 7 +++++++ .../Object.ToJObject.cs | 1 + src/Shims/Nuke.Common/Nuke.Common.csproj | 6 ++++++ tests/Fallout.Common.Tests/SettingsTest.cs | 2 ++ tests/Fallout.Tooling.Tests/OptionsTest.cs | 2 ++ .../ToolOptionsArgumentsTest.cs | 2 ++ .../Text/SerializationTest.cs | 2 ++ 14 files changed, 50 insertions(+), 7 deletions(-) diff --git a/src/Fallout.Common/CI/GitHubActions/GitHubActions.cs b/src/Fallout.Common/CI/GitHubActions/GitHubActions.cs index 638914381..5f2e13e36 100644 --- a/src/Fallout.Common/CI/GitHubActions/GitHubActions.cs +++ b/src/Fallout.Common/CI/GitHubActions/GitHubActions.cs @@ -114,8 +114,10 @@ internal GitHubActions() public JObject GitHubEvent => _eventContext.Value; public bool IsPullRequest => EventName == "pull_request"; +#pragma warning disable CS0618 // JObjectExtensions retires in v11; PullRequestNumber/Action follow when GitHubEvent migrates to JsonObject (API-break, separate PR). public int? PullRequestNumber => GitHubEvent.GetPropertyValue("number"); public string PullRequestAction => GitHubEvent.GetPropertyStringValue("action"); +#pragma warning restore CS0618 public AbsolutePath StepSummaryFile => EnvironmentInfo.GetVariable("GITHUB_STEP_SUMMARY"); diff --git a/src/Fallout.Common/Tools/SignPath/SignPathTasks.cs b/src/Fallout.Common/Tools/SignPath/SignPathTasks.cs index 6251e0664..c7b302168 100644 --- a/src/Fallout.Common/Tools/SignPath/SignPathTasks.cs +++ b/src/Fallout.Common/Tools/SignPath/SignPathTasks.cs @@ -10,8 +10,8 @@ using System.Net.Http; using System.Net.Http.Headers; using System.Text; +using System.Text.Json.Nodes; using System.Threading.Tasks; -using Newtonsoft.Json.Linq; using Fallout.Common.CI.AppVeyor; using Fallout.Common.IO; using Fallout.Common.Utilities; @@ -71,7 +71,7 @@ public static async Task GetSigningRequestUrlViaAppVeyor( using var httpClient = CreateAuthorizedHttpClient(authToken, DefaultHttpClientTimeout); var response = await httpClient.PostAsync( GetSignPathAppVeyorIntegrationUrl(organizationId, projectSlug, signingPolicySlug), - new StringContent(content.ToJson(), Encoding.UTF8, contentType)); + new StringContent(content.ToJson(JsonExtensions.DefaultSerializerOptions), Encoding.UTF8, contentType)); response.AssertStatusCode(HttpStatusCode.Created); Log.Information("Signing request created: {Url}", response.Headers.Location.AbsoluteUri.Replace("api/v1", "Web")); @@ -149,11 +149,11 @@ private static string GetSignedArtifactUrl(HttpClient httpClient, string signing { var response = SendGetRequestWithRetry(httpClient, signingRequestUrl); var rawContent = response.Content.ReadAsStringAsync().GetAwaiter().GetResult(); - var jsonContent = rawContent.GetJson(); - signingRequestStatus = jsonContent["status"].NotNull().Value(); + var jsonContent = rawContent.GetJsonObject(); + signingRequestStatus = jsonContent["status"].NotNull().GetValue(); signedArtifactUrl = signingRequestStatus switch { - SigningRequestStatus.Completed => jsonContent["signedArtifactLink"].NotNull().Value(), + SigningRequestStatus.Completed => jsonContent["signedArtifactLink"].NotNull().GetValue(), SigningRequestStatus.Failed => null, SigningRequestStatus.Denied => null, SigningRequestStatus.Cancelled => null, @@ -255,8 +255,8 @@ private static HttpResponseMessage AssertStatusCode(this HttpResponseMessage res if (response.StatusCode != statusCode) { var content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult(); - var jobject = content.GetJson(); - Assert.Fail($"[{response.StatusCode}] {jobject.GetChildren("").Select(x => x.Value()).JoinNewLine()}"); + var jobject = content.GetJsonObject(); + Assert.Fail($"[{response.StatusCode}] {jobject.GetChildren("").Select(x => x.GetValue()).JoinNewLine()}"); } return response; diff --git a/src/Fallout.Tooling/ProcessExtensions.cs b/src/Fallout.Tooling/ProcessExtensions.cs index c67097fbe..0bf06a77b 100644 --- a/src/Fallout.Tooling/ProcessExtensions.cs +++ b/src/Fallout.Tooling/ProcessExtensions.cs @@ -52,7 +52,9 @@ public static string StdToText(this IEnumerable output) public static T StdToJson(this IEnumerable output) { +#pragma warning disable CS0618 // GetJson(Newtonsoft) retires in v11; this whole StdToJson surface is part of the Fallout.Tooling migration follow-up. return output.StdToText().GetJson(); +#pragma warning restore CS0618 } public static JObject StdToJson(this IEnumerable output) diff --git a/src/Fallout.Utilities.Text.Json/AllWritableContractResolver.cs b/src/Fallout.Utilities.Text.Json/AllWritableContractResolver.cs index 40fbef868..f8a1a7bab 100644 --- a/src/Fallout.Utilities.Text.Json/AllWritableContractResolver.cs +++ b/src/Fallout.Utilities.Text.Json/AllWritableContractResolver.cs @@ -14,6 +14,7 @@ namespace Fallout.Common.Tooling; /// /// Treats all properties as writable. /// +[Obsolete("Newtonsoft-specific contract resolver. System.Text.Json handles records and init-only properties natively, so this workaround is unnecessary on the STJ path. Scheduled for removal in v11 (#83).")] internal class AllWritableContractResolver : DefaultContractResolver { protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) diff --git a/src/Fallout.Utilities.Text.Json/Base64JsonConverter.cs b/src/Fallout.Utilities.Text.Json/Base64JsonConverter.cs index 9268d196d..d4875f3bd 100644 --- a/src/Fallout.Utilities.Text.Json/Base64JsonConverter.cs +++ b/src/Fallout.Utilities.Text.Json/Base64JsonConverter.cs @@ -11,6 +11,7 @@ namespace Fallout.Utilities.Text.Json; +[Obsolete("Newtonsoft-specific Base64 JSON type converter with zero internal callers. Scheduled for removal in v11 (#83); consumers needing this should pin Newtonsoft.Json directly.")] public class Base64JsonConverter : TypeConverter { public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) diff --git a/src/Fallout.Utilities.Text.Json/JObject.GetChildren.cs b/src/Fallout.Utilities.Text.Json/JObject.GetChildren.cs index 86ce95afd..b663e298b 100644 --- a/src/Fallout.Utilities.Text.Json/JObject.GetChildren.cs +++ b/src/Fallout.Utilities.Text.Json/JObject.GetChildren.cs @@ -3,20 +3,27 @@ // Distributed under the MIT License. // https://github.com/ChrisonSimtian/Fallout/blob/main/LICENSE +using System; using Newtonsoft.Json.Linq; namespace Fallout.Common.Utilities; public static partial class JObjectExtensions { + [Obsolete("Use the JsonObject overload in JsonNodeExtensions instead. Newtonsoft.Json surface is scheduled for removal in v11 (#83).")] public static JEnumerable GetChildren(this JObject jobject, string name) where T : JToken { +#pragma warning disable CS0618 // Newtonsoft helpers retire together. return jobject.GetPropertyValue(name).Children(); +#pragma warning restore CS0618 } + [Obsolete("Use the JsonObject overload in JsonNodeExtensions instead. Newtonsoft.Json surface is scheduled for removal in v11 (#83).")] public static JEnumerable GetChildren(this JObject jobject, string name) { +#pragma warning disable CS0618 // Newtonsoft helpers retire together. return jobject.GetChildren(name); +#pragma warning restore CS0618 } } diff --git a/src/Fallout.Utilities.Text.Json/JObject.GetPropertyValue.cs b/src/Fallout.Utilities.Text.Json/JObject.GetPropertyValue.cs index 3db24e8ce..76455d404 100644 --- a/src/Fallout.Utilities.Text.Json/JObject.GetPropertyValue.cs +++ b/src/Fallout.Utilities.Text.Json/JObject.GetPropertyValue.cs @@ -11,6 +11,7 @@ namespace Fallout.Common.Utilities; public static partial class JObjectExtensions { + [Obsolete("Use the JsonObject overload in JsonNodeExtensions instead. Newtonsoft.Json surface is scheduled for removal in v11 (#83).")] public static T GetPropertyValueOrNull(this JObject jobject, string name) { var property = jobject.Property(name); @@ -19,19 +20,26 @@ public static T GetPropertyValueOrNull(this JObject jobject, string name) : default; } + [Obsolete("Use the JsonObject overload in JsonNodeExtensions instead. Newtonsoft.Json surface is scheduled for removal in v11 (#83).")] public static T GetPropertyValue(this JObject jobject, string name) { var property = jobject.Property(name).NotNull($"Property '{name}' not found"); return property.Value.Value(); } + [Obsolete("Use the JsonObject overload in JsonNodeExtensions instead. Newtonsoft.Json surface is scheduled for removal in v11 (#83).")] public static JObject GetPropertyValue(this JObject jobject, string name) { +#pragma warning disable CS0618 // Newtonsoft helpers retire together. return jobject.GetPropertyValue(name); +#pragma warning restore CS0618 } + [Obsolete("Use the JsonObject overload in JsonNodeExtensions instead. Newtonsoft.Json surface is scheduled for removal in v11 (#83).")] public static string GetPropertyStringValue(this JObject jobject, string name) { +#pragma warning disable CS0618 // Newtonsoft helpers retire together. return jobject.GetPropertyValue(name); +#pragma warning restore CS0618 } } diff --git a/src/Fallout.Utilities.Text.Json/JsonExtensions.cs b/src/Fallout.Utilities.Text.Json/JsonExtensions.cs index bb4cc69fb..537922c0b 100644 --- a/src/Fallout.Utilities.Text.Json/JsonExtensions.cs +++ b/src/Fallout.Utilities.Text.Json/JsonExtensions.cs @@ -17,6 +17,8 @@ namespace Fallout.Common.Utilities; public static class JsonExtensions { + [Obsolete("Use DefaultSerializerOptions (JsonSerializerOptions) instead. Newtonsoft.Json surface is scheduled for removal in v11 (#83).")] +#pragma warning disable CS0618 // AllWritableContractResolver retires alongside. public static JsonSerializerSettings DefaultSerializerSettings = new() { @@ -24,6 +26,7 @@ public static class JsonExtensions DefaultValueHandling = DefaultValueHandling.Ignore, ContractResolver = new AllWritableContractResolver() }; +#pragma warning restore CS0618 public static JsonSerializerOptions DefaultSerializerOptions { get; } = new() @@ -46,7 +49,9 @@ public static string ToJson( JsonSerializerSettings serializerSettings = null, Formatting formatting = Formatting.Indented) { +#pragma warning disable CS0618 // DefaultSerializerSettings retires alongside. return JsonConvert.SerializeObject(obj, formatting, serializerSettings ?? DefaultSerializerSettings); +#pragma warning restore CS0618 } /// @@ -55,7 +60,9 @@ public static string ToJson( [Obsolete("Use the JsonSerializerOptions overload instead. Newtonsoft.Json surface is scheduled for removal in v11 as part of the System.Text.Json migration (#83).")] public static T GetJson(this string content, JsonSerializerSettings serializerSettings = null) { +#pragma warning disable CS0618 // DefaultSerializerSettings retires alongside. return JsonConvert.DeserializeObject(content, serializerSettings ?? DefaultSerializerSettings); +#pragma warning restore CS0618 } /// diff --git a/src/Fallout.Utilities.Text.Json/Object.ToJObject.cs b/src/Fallout.Utilities.Text.Json/Object.ToJObject.cs index f8e50da1a..dd02b589c 100644 --- a/src/Fallout.Utilities.Text.Json/Object.ToJObject.cs +++ b/src/Fallout.Utilities.Text.Json/Object.ToJObject.cs @@ -18,6 +18,7 @@ namespace Fallout.Common.Utilities; // invisible to callers and a rename is the cleanest fix. public static class JsonObjectExtensions { + [Obsolete("Returns a Newtonsoft JObject. For new code, use System.Text.Json.Nodes.JsonNode.Parse(System.Text.Json.JsonSerializer.Serialize(obj)) or JsonSerializer.SerializeToNode(obj). Scheduled for removal in v11 (#83).")] public static JObject ToJObject(this object obj, JsonSerializer serializer = null) { serializer ??= JsonSerializer.CreateDefault(); diff --git a/src/Shims/Nuke.Common/Nuke.Common.csproj b/src/Shims/Nuke.Common/Nuke.Common.csproj index 488542f7b..e7bc3bf19 100644 --- a/src/Shims/Nuke.Common/Nuke.Common.csproj +++ b/src/Shims/Nuke.Common/Nuke.Common.csproj @@ -18,6 +18,12 @@ false + + $(NoWarn);CS0618 diff --git a/tests/Fallout.Common.Tests/SettingsTest.cs b/tests/Fallout.Common.Tests/SettingsTest.cs index ecdf0ee46..281945c2f 100644 --- a/tests/Fallout.Common.Tests/SettingsTest.cs +++ b/tests/Fallout.Common.Tests/SettingsTest.cs @@ -173,6 +173,7 @@ public void TestDocker() [Fact] public Task TestDiscord() { +#pragma warning disable CS0618 // Test pins Options.JsonSerializerSettings round-trip; STJ equivalents follow in Fallout.Tooling's #83 migration. var result = new DiscordMessage() .SetNonce("nonce") .SetChannelId("channel-id") @@ -181,6 +182,7 @@ public Task TestDiscord() .SetAuthor(_ => _ .SetName("author-name"))) .ToJson(Options.JsonSerializerSettings); +#pragma warning restore CS0618 return Verifier.Verify(result); } diff --git a/tests/Fallout.Tooling.Tests/OptionsTest.cs b/tests/Fallout.Tooling.Tests/OptionsTest.cs index 536d433d9..2b74cd19d 100644 --- a/tests/Fallout.Tooling.Tests/OptionsTest.cs +++ b/tests/Fallout.Tooling.Tests/OptionsTest.cs @@ -147,7 +147,9 @@ public Task TestSerialization() options.Set(() => LookupValue, new LookupTable { ["key"] = new[] { 1, 2, 3 } }); options.Set(() => NestedValue, options); +#pragma warning disable CS0618 // Test pins Options.JsonSerializerSettings round-trip; STJ equivalents follow in Fallout.Tooling's #83 migration. return Verifier.Verify(options.ToJson(Options.JsonSerializerSettings)); +#pragma warning restore CS0618 } } diff --git a/tests/Fallout.Tooling.Tests/ToolOptionsArgumentsTest.cs b/tests/Fallout.Tooling.Tests/ToolOptionsArgumentsTest.cs index d9b87f82b..2d94f612b 100644 --- a/tests/Fallout.Tooling.Tests/ToolOptionsArgumentsTest.cs +++ b/tests/Fallout.Tooling.Tests/ToolOptionsArgumentsTest.cs @@ -191,7 +191,9 @@ private static T SetInternalOptions(object obj) where T : ToolOptions, new() { var options = new T(); +#pragma warning disable CS0618 // ToJObject (Newtonsoft) retires in v11 alongside ToolOptions.InternalOptions which is itself JObject-typed. options.InternalOptions = obj.ToJObject(Options.JsonSerializer); +#pragma warning restore CS0618 return options; } } diff --git a/tests/Fallout.Utilities.Tests/Text/SerializationTest.cs b/tests/Fallout.Utilities.Tests/Text/SerializationTest.cs index cfb213c29..9f5b8bf39 100644 --- a/tests/Fallout.Utilities.Tests/Text/SerializationTest.cs +++ b/tests/Fallout.Utilities.Tests/Text/SerializationTest.cs @@ -20,8 +20,10 @@ public class SerializationTest public void JsonTest() { var data = CreateData("Json"); +#pragma warning disable CS0618 // Test pins Newtonsoft round-trip semantics; STJ equivalents will get their own test cases in v11. var content = data.ToJson(); var copy = content.GetJson(); +#pragma warning restore CS0618 copy.Should().BeEquivalentTo(data); }