Skip to content

Commit e9e1932

Browse files
committed
remove dependency on Newtonsoft.Json
1 parent 06b0eaf commit e9e1932

2 files changed

Lines changed: 72 additions & 30 deletions

File tree

‎src/GitExtensions.AzureDevOpsCommitMessage/GitExtensions.AzureDevOpsCommitMessage.csproj‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
<PackageReference Include="System.ComponentModel.Composition" Version="6.0.0" />
3939
<PackageReference Include="GitExtensions.Extensibility" Version="7.0.0.135" />
4040
<PackageReference Include="Microsoft.VisualStudio.Threading" Version="17.13.61" />
41-
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
4241
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="10.0.401" PrivateAssets="All" />
4342
</ItemGroup>
4443

‎src/GitExtensions.AzureDevOpsCommitMessage/Plugin.cs‎

Lines changed: 72 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
using GitUIPluginInterfaces;
1818
using GitExtensions.Extensibility.Plugins;
1919
using GitExtensions.Extensibility.Settings;
20-
using Newtonsoft.Json.Linq;
20+
using System.Text.Json;
21+
using System.Text.Json.Nodes;
2122
using ResourceManager;
2223
using GitExtensions.Extensibility.Git;
2324
using GitExtensions.Extensibility.Settings.UserControls;
@@ -397,16 +398,23 @@ private async Task<IList<CommitTemplate>> GetCommitTemplatesAsync(HttpClient cli
397398
return new[] { new CommitTemplate($"{Description} {Error}", ex.ToString()) };
398399
}
399400
}
400-
401401
private IEnumerable<(string id, string url)> GetWorkitems(string jsonWorkitems)
402402
{
403-
var workItems = JObject.Parse(jsonWorkitems)["workItems"];
404-
if (workItems == null)
403+
using var doc = JsonDocument.Parse(jsonWorkitems);
404+
if (!doc.RootElement.TryGetProperty("workItems", out var workItemsElement) || workItemsElement.ValueKind != JsonValueKind.Array)
405405
{
406406
return Enumerable.Empty<(string id, string url)>();
407407
}
408408

409-
return workItems.Select(w => (w["id"].ToString(), w["url"].ToString()));
409+
var result = new List<(string id, string url)>();
410+
foreach (var item in workItemsElement.EnumerateArray())
411+
{
412+
var id = item.TryGetProperty("id", out var idEl) ? (idEl.ValueKind == JsonValueKind.String ? idEl.GetString() : idEl.GetRawText()) : string.Empty;
413+
var url = item.TryGetProperty("url", out var urlEl) ? urlEl.GetString() ?? urlEl.GetRawText() : string.Empty;
414+
result.Add((id ?? string.Empty, url ?? string.Empty));
415+
}
416+
417+
return result;
410418
}
411419

412420
private async Task<CommitTemplate> GetWorkItemAsync(HttpClient client, string id, string url, string template)
@@ -433,7 +441,12 @@ private async Task<CommitTemplate> GetWorkItemAsync(HttpClient client, string id
433441

434442
private CommitTemplate GetCommitTemplateFromWorkitemData(string id, string template, string jsonWorkitem)
435443
{
436-
var workItemData = JObject.Parse(jsonWorkitem)["fields"];
444+
using var doc = JsonDocument.Parse(jsonWorkitem);
445+
if (!doc.RootElement.TryGetProperty("fields", out var workItemData))
446+
{
447+
workItemData = default;
448+
}
449+
437450
if (_btnPreview != null)
438451
{
439452
_allFieldsAndValues = ExtractAllFields(workItemData);
@@ -459,81 +472,96 @@ private string Elide(string value)
459472
return value.Length > 80 ? value.Substring(0, 80) + "[...]" : value;
460473
}
461474

462-
private string ExtractAllFields(JToken fields)
475+
private string ExtractAllFields(JsonElement fields)
463476
{
464-
List<string> allFields = new List<string>();
465-
foreach (var pair in (JObject)fields)
477+
var allFields = new List<string>();
478+
if (fields.ValueKind != JsonValueKind.Object)
466479
{
467-
if (!pair.Value.HasValues)
480+
return string.Empty;
481+
}
482+
483+
foreach (var prop in fields.EnumerateObject())
484+
{
485+
if (prop.Value.ValueKind != JsonValueKind.Object)
468486
{
469-
allFields.Add($"{{{pair.Key}}}: {Elide(pair.Value.ToString())}");
487+
allFields.Add($"{{{prop.Name}}}: {Elide(ElementToString(prop.Value))}");
470488
}
471489
else
472490
{
473-
allFields.AddRange(FlattenFieldsHierarchy(pair.Key, pair.Value));
491+
allFields.AddRange(FlattenFieldsHierarchy(prop.Name, prop.Value));
474492
}
475493
}
476494

477495
return string.Join(Environment.NewLine, allFields.OrderBy(s => s));
478496
}
479497

480-
private IEnumerable<string> FlattenFieldsHierarchy(string key, JToken fields)
498+
private IEnumerable<string> FlattenFieldsHierarchy(string key, JsonElement fields)
481499
{
482-
foreach (var pair in (JObject)fields)
500+
if (fields.ValueKind != JsonValueKind.Object)
501+
{
502+
yield break;
503+
}
504+
505+
foreach (var prop in fields.EnumerateObject())
483506
{
484-
if (!pair.Value.HasValues)
507+
if (prop.Value.ValueKind != JsonValueKind.Object)
485508
{
486-
yield return $"{{{key}|{pair.Key}}}: {Elide(pair.Value.ToString())}";
509+
yield return $"{{{key}|{prop.Name}}}: {Elide(ElementToString(prop.Value))}";
487510
}
488511
else
489512
{
490-
foreach (string value in FlattenFieldsHierarchy(key + "|" + pair.Key, pair.Value))
513+
foreach (var value in FlattenFieldsHierarchy(key + "|" + prop.Name, prop.Value))
491514
{
492515
yield return value;
493516
}
494517
}
495518
}
496519
}
497520

498-
private string PopulateTemplate(string titleTemplate, string id, JToken workitem)
521+
private string PopulateTemplate(string titleTemplate, string id, JsonElement workitem)
499522
{
500523
return ExtractWorkItemField(titleTemplate.Replace("{id}", id), workitem);
501524
}
502525

503-
private static bool TryGetWorkItemValue(JToken workitem, string workItemField, out string value)
526+
private static bool TryGetWorkItemValue(JsonElement workitem, string workItemField, out string value)
504527
{
528+
value = null;
505529
if (workItemField.Contains('|'))
506530
{
507531
var fields = workItemField.Split('|');
532+
var current = workitem;
508533
foreach (var field in fields)
509534
{
510-
var foundValue = workitem[field];
511-
if (foundValue == null)
535+
if (current.ValueKind != JsonValueKind.Object || !current.TryGetProperty(field, out var foundValue))
512536
{
513537
value = null;
514538
return false;
515539
}
516540

517-
workitem = foundValue;
541+
current = foundValue;
518542
}
519543

520-
value = workitem.ToString();
544+
value = ElementToString(current);
521545
return true;
522546
}
523547
else
524548
{
525-
var foundValue = workitem[workItemField];
526-
value = foundValue?.ToString();
527-
if (workItemField == "System.Description")
549+
if (workitem.ValueKind == JsonValueKind.Object && workitem.TryGetProperty(workItemField, out var foundValue))
528550
{
529-
value = ExtractTextFromHtml(value);
551+
value = ElementToString(foundValue);
552+
if (workItemField == "System.Description")
553+
{
554+
value = ExtractTextFromHtml(value);
555+
}
556+
557+
return value != null;
530558
}
531559

532-
return value != null;
560+
return false;
533561
}
534562
}
535563

536-
public static string ExtractWorkItemField(string pattern, JToken workitem)
564+
public static string ExtractWorkItemField(string pattern, JsonElement workitem)
537565
{
538566
if (string.IsNullOrWhiteSpace(pattern))
539567
{
@@ -557,6 +585,21 @@ public static string ExtractWorkItemField(string pattern, JToken workitem)
557585
return pattern;
558586
}
559587

588+
private static string ElementToString(JsonElement el)
589+
{
590+
if (el.ValueKind == JsonValueKind.String)
591+
{
592+
return el.GetString();
593+
}
594+
595+
if (el.ValueKind == JsonValueKind.Null || el.ValueKind == JsonValueKind.Undefined)
596+
{
597+
return null;
598+
}
599+
600+
return el.GetRawText();
601+
}
602+
560603
public static string ExtractTextFromHtml(string html)
561604
{
562605
if (string.IsNullOrWhiteSpace(html))

0 commit comments

Comments
 (0)