Skip to content

Commit 56a1717

Browse files
committed
Migrate Spdx22ComponentDetector from Newtonsoft.Json to System.Text.Json
- Replace `JObject`/`JsonTextReader` with `JsonDocument.ParseAsync` - Convert `JObject` property access to `JsonElement.TryGetProperty` pattern - Make `OnFileFoundAsync` properly `async` - Update exception handling from `JsonReaderException` to `JsonException`
1 parent f096423 commit 56a1717

File tree

1 file changed

+35
-30
lines changed

1 file changed

+35
-30
lines changed

src/Microsoft.ComponentDetection.Detectors/spdx/Spdx22ComponentDetector.cs

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,13 @@ namespace Microsoft.ComponentDetection.Detectors.Spdx;
66
using System.IO;
77
using System.Linq;
88
using System.Security.Cryptography;
9+
using System.Text.Json;
910
using System.Threading;
1011
using System.Threading.Tasks;
1112
using Microsoft.ComponentDetection.Contracts;
1213
using Microsoft.ComponentDetection.Contracts.Internal;
1314
using Microsoft.ComponentDetection.Contracts.TypedComponent;
1415
using Microsoft.Extensions.Logging;
15-
using Newtonsoft.Json;
16-
using Newtonsoft.Json.Linq;
1716

1817
/// <summary>
1918
/// Spdx22ComponentDetector discover SPDX SBOM files in JSON format and create components with the information about
@@ -44,7 +43,7 @@ public Spdx22ComponentDetector(
4443

4544
public override IList<string> SearchPatterns => ["*.spdx.json"];
4645

47-
protected override Task OnFileFoundAsync(ProcessRequest processRequest, IDictionary<string, string> detectorArgs, CancellationToken cancellationToken = default)
46+
protected override async Task OnFileFoundAsync(ProcessRequest processRequest, IDictionary<string, string> detectorArgs, CancellationToken cancellationToken = default)
4847
{
4948
this.Logger.LogDebug("Discovered SPDX2.2 manifest file at: {ManifestLocation}", processRequest.ComponentStream.Location);
5049
var file = processRequest.ComponentStream;
@@ -56,31 +55,22 @@ protected override Task OnFileFoundAsync(ProcessRequest processRequest, IDiction
5655
// Reset buffer to starting position after hash generation.
5756
file.Stream.Seek(0, SeekOrigin.Begin);
5857

59-
using var sr = new StreamReader(file.Stream);
60-
using var reader = new JsonTextReader(sr);
61-
var serializer = new JsonSerializer();
62-
6358
try
6459
{
65-
var document = serializer.Deserialize<JObject>(reader);
66-
if (document != null)
60+
using var document = await JsonDocument.ParseAsync(file.Stream, cancellationToken: cancellationToken).ConfigureAwait(false);
61+
var root = document.RootElement;
62+
63+
if (this.IsSPDXVersionSupported(root))
6764
{
68-
if (this.IsSPDXVersionSupported(document))
69-
{
70-
var sbomComponent = this.ConvertJObjectToSbomComponent(processRequest, document, hash);
71-
processRequest.SingleFileComponentRecorder.RegisterUsage(new DetectedComponent(sbomComponent));
72-
}
73-
else
74-
{
75-
this.Logger.LogWarning("Discovered SPDX at {ManifestLocation} is not SPDX-2.2 document, skipping", processRequest.ComponentStream.Location);
76-
}
65+
var sbomComponent = this.ConvertJsonElementToSbomComponent(processRequest, root, hash);
66+
processRequest.SingleFileComponentRecorder.RegisterUsage(new DetectedComponent(sbomComponent));
7767
}
7868
else
7969
{
80-
this.Logger.LogWarning("Discovered SPDX file at {ManifestLocation} is not a valid document, skipping", processRequest.ComponentStream.Location);
70+
this.Logger.LogWarning("Discovered SPDX at {ManifestLocation} is not SPDX-2.2 document, skipping", processRequest.ComponentStream.Location);
8171
}
8272
}
83-
catch (JsonReaderException)
73+
catch (JsonException)
8474
{
8575
this.Logger.LogWarning("Unable to parse file at {ManifestLocation}, skipping", processRequest.ComponentStream.Location);
8676
}
@@ -89,25 +79,40 @@ protected override Task OnFileFoundAsync(ProcessRequest processRequest, IDiction
8979
{
9080
this.Logger.LogError(e, "Error while processing SPDX file at {ManifestLocation}", processRequest.ComponentStream.Location);
9181
}
92-
93-
return Task.CompletedTask;
9482
}
9583

96-
private bool IsSPDXVersionSupported(JObject document) => this.supportedSPDXVersions.Contains(document["spdxVersion"]?.ToString(), StringComparer.OrdinalIgnoreCase);
84+
private bool IsSPDXVersionSupported(JsonElement document)
85+
{
86+
if (document.TryGetProperty("spdxVersion", out var versionElement))
87+
{
88+
var version = versionElement.GetString();
89+
return this.supportedSPDXVersions.Contains(version, StringComparer.OrdinalIgnoreCase);
90+
}
9791

98-
private SpdxComponent ConvertJObjectToSbomComponent(ProcessRequest processRequest, JObject document, string fileHash)
92+
return false;
93+
}
94+
95+
private SpdxComponent ConvertJsonElementToSbomComponent(ProcessRequest processRequest, JsonElement document, string fileHash)
9996
{
100-
var sbomNamespace = document["documentNamespace"]?.ToString();
101-
var rootElements = document["documentDescribes"]?.ToObject<string[]>();
102-
var name = document["name"]?.ToString();
103-
var spdxVersion = document["spdxVersion"]?.ToString();
97+
var sbomNamespace = document.TryGetProperty("documentNamespace", out var nsElement) ? nsElement.GetString() : null;
98+
var name = document.TryGetProperty("name", out var nameElement) ? nameElement.GetString() : null;
99+
var spdxVersion = document.TryGetProperty("spdxVersion", out var versionElement2) ? versionElement2.GetString() : null;
100+
101+
string[] rootElements = null;
102+
if (document.TryGetProperty("documentDescribes", out var describesElement) && describesElement.ValueKind == JsonValueKind.Array)
103+
{
104+
rootElements = describesElement.EnumerateArray()
105+
.Select(e => e.GetString())
106+
.Where(s => s != null)
107+
.ToArray();
108+
}
104109

105-
if (rootElements?.Length > 1)
110+
if (rootElements is { Length: > 1 })
106111
{
107112
this.Logger.LogWarning("SPDX file at {ManifestLocation} has more than one element in documentDescribes, first will be selected as root element.", processRequest.ComponentStream.Location);
108113
}
109114

110-
if (rootElements != null && rootElements.Length == 0)
115+
if (rootElements is { Length: 0 })
111116
{
112117
this.Logger.LogWarning("SPDX file at {ManifestLocation} does not have root elements in documentDescribes section, considering SPDXRef-Document as a root element.", processRequest.ComponentStream.Location);
113118
}

0 commit comments

Comments
 (0)