Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serialize SPDX reference category with hyphens so it matches spdx 2.2.2 (breaking!) #269

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 41 additions & 1 deletion src/CycloneDX.Spdx/Models/v2_2/ExternalRef.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
// Copyright (c) OWASP Foundation. All Rights Reserved.

using System;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text.Json.Serialization;
using System.Xml.Serialization;

namespace CycloneDX.Spdx.Models.v2_2
Expand All @@ -28,8 +31,45 @@ public class ExternalRef
/// <summary>
/// Category for the external reference
/// </summary>
[XmlElement("referenceCategory")]
[XmlIgnore]
public ExternalRefCategory ReferenceCategory { get; set; }

/// <summary>
/// Category for the external reference, adjusted to allow values with hyphens and underscores
/// </summary>
[XmlElement("referenceCategory")]
[JsonIgnore]
public string ReferenceCategoryAsString
{
get
{
switch (ReferenceCategory)
{
case ExternalRefCategory.PACKAGE_MANAGER:
return "PACKAGE-MANAGER";
default:
return ReferenceCategory.ToString();
}
}
set
{
switch (value.ToUpperInvariant())
{
case "OTHER":
ReferenceCategory = ExternalRefCategory.OTHER;
break;
case "SECURITY":
ReferenceCategory = ExternalRefCategory.SECURITY;
break;
case "PACKAGE_MANAGER":
case "PACKAGE-MANAGER":
ReferenceCategory = ExternalRefCategory.PACKAGE_MANAGER;
break;
default:
throw new InvalidOperationException();
}
}
}

/// <summary>
/// The unique string with no spaces necessary to access the package-specific information, metadata, or content within the target location. The format of the locator is subject to constraints defined by the &lt;type&gt;.
Expand Down
2 changes: 2 additions & 0 deletions src/CycloneDX.Spdx/Models/v2_2/ExternalRefCategory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@
// Copyright (c) OWASP Foundation. All Rights Reserved.

using System;
using System.Runtime.Serialization;

namespace CycloneDX.Spdx.Models.v2_2
{
public enum ExternalRefCategory
{
OTHER,
SECURITY,
[EnumMember(Value = "PACKAGE-MANAGER")]
PACKAGE_MANAGER,
}
}
2 changes: 1 addition & 1 deletion src/CycloneDX.Spdx/Schemas/spdx-2.2.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@
"referenceCategory" : {
"description" : "Category for the external reference",
"type" : "string",
"enum" : [ "OTHER", "PERSISTENT_ID", "SECURITY", "PACKAGE_MANAGER" ]
"enum" : [ "OTHER", "PERSISTENT_ID", "SECURITY", "PACKAGE_MANAGER", "PACKAGE-MANAGER", "PERSISTENT-ID" ]
},
"referenceLocator" : {
"description" : "The unique string with no spaces necessary to access the package-specific information, metadata, or content within the target location. The format of the locator is subject to constraints defined by the <type>.",
Expand Down
62 changes: 62 additions & 0 deletions src/CycloneDX.Spdx/Serialization/Converters/HyphenEnumConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// This file is part of CycloneDX Library for .NET
//
// Licensed under the Apache License, Version 2.0 (the “License”);
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an “AS IS” BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) OWASP Foundation. All Rights Reserved.

using System;
using System.Diagnostics.Contracts;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace CycloneDX.Spdx.Serialization.Converters
{

public class HyphenEnumConverter<T> : JsonConverter<T> where T: struct
{
public override T Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.Null
|| reader.TokenType != JsonTokenType.String)
{
throw new JsonException();
}

var enumString = reader.GetString();

T enumValue;
var success = Enum.TryParse<T>(enumString.Replace("-", "_"), ignoreCase: true, out enumValue);
if (success)
{
return enumValue;
}
else
{
throw new JsonException();
}
}

public override void Write(
Utf8JsonWriter writer,
T value,
JsonSerializerOptions options)
{
Contract.Requires(writer != null);
writer.WriteStringValue(value.ToString().Replace('_', '-'));
}
}
}
3 changes: 3 additions & 0 deletions src/CycloneDX.Spdx/Serialization/JsonSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using CycloneDX.Spdx.Models.v2_2;
using CycloneDX.Spdx.Serialization.Converters;

namespace CycloneDX.Spdx.Serialization
{
Expand All @@ -38,6 +40,7 @@ public static JsonSerializerOptions GetJsonSerializerOptions_v2_2()
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
};
options.Converters.Add(new HyphenEnumConverter<ExternalRefCategory>());
options.Converters.Add(new JsonStringEnumConverter());
return options;
}
Expand Down
4 changes: 4 additions & 0 deletions tests/CycloneDX.Spdx.Tests/CycloneDX.Spdx.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,8 @@
<ProjectReference Include="..\..\src\CycloneDX.Spdx\CycloneDX.Spdx.csproj" />
</ItemGroup>

<ItemGroup>
<Folder Include="__snapshots__\" />
</ItemGroup>

</Project>
2 changes: 2 additions & 0 deletions tests/CycloneDX.Spdx.Tests/JsonSerializerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class JsonSerializerTests
{
[Theory]
[InlineData("document")]
[InlineData("document-with-hyphens-in-external-reference-category")]
public void JsonRoundTripTest(string baseFilename)
{
var resourceFilename = Path.Join("Resources", "v2.2", baseFilename + ".json");
Expand All @@ -42,6 +43,7 @@ public void JsonRoundTripTest(string baseFilename)

[Theory]
[InlineData("document")]
[InlineData("document-with-hyphens-in-external-reference-category")]
public async Task JsonAsyncRoundTripTest(string baseFilename)
{
var resourceFilename = Path.Join("Resources", "v2.2", baseFilename + ".json");
Expand Down
2 changes: 2 additions & 0 deletions tests/CycloneDX.Spdx.Tests/JsonValidatorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class JsonValidatorTests
{
[Theory]
[InlineData("document")]
[InlineData("document-with-hyphens-in-external-reference-category")]
public void ValidateJsonStringTest(string baseFilename)
{
var resourceFilename = Path.Join("Resources", "v2.2", baseFilename + ".json");
Expand All @@ -41,6 +42,7 @@ public void ValidateJsonStringTest(string baseFilename)

[Theory]
[InlineData("document")]
[InlineData("document-with-hyphens-in-external-reference-category")]
public async Task ValidateJsonStreamTest(string baseFilename)
{
var resourceFilename = Path.Join("Resources", "v2.2", baseFilename + ".json");
Expand Down
Loading