From d6cdb892c56f6d9d2695cfaf264a386fdcad3fd8 Mon Sep 17 00:00:00 2001 From: andreas hilti <69210561+andreas-hilti@users.noreply.github.com> Date: Sun, 20 Sep 2026 16:37:39 +0200 Subject: [PATCH] fix serialization of enum with Null values Signed-off-by: andreas hilti <69210561+andreas-hilti@users.noreply.github.com> --- .../Models/Algorithms/AlgorithmProperties.cs | 3 +++ src/CycloneDX.Core/Models/Crypto/CryptoProperties.cs | 3 +++ src/CycloneDX.Core/Models/Crypto/ProtocolProperties.cs | 3 +++ .../Models/Crypto/RelatedCryptoMaterialProperties.cs | 7 ++++++- src/CycloneDX.Core/Models/DataClassification.cs | 5 ++++- src/CycloneDX.Core/Models/DataFlow.cs | 5 ++++- src/CycloneDX.Core/Models/EnergyConsumption/Co2Measure.cs | 4 ++++ .../Models/EnergyConsumption/EnergyConsumptions.cs | 4 ++++ .../Models/EnergyConsumption/EnergyMeasure.cs | 4 ++++ .../Models/EnergyConsumption/EnergyProvider.cs | 4 ++++ src/CycloneDX.Core/Models/EvidenceIdentity.cs | 5 ++++- src/CycloneDX.Core/Models/Hash.cs | 8 ++++++-- src/CycloneDX.Core/Models/Issue.cs | 6 +++++- src/CycloneDX.Core/Models/LicenseChoice.cs | 2 +- src/CycloneDX.Core/Models/Patch.cs | 6 +++++- src/CycloneDX.Core/Models/Patent.cs | 5 ++++- src/CycloneDX.Core/Models/PatentAssertion.cs | 5 ++++- src/CycloneDX.Core/Models/Vulnerabilities/Analysis.cs | 8 +++++++- 18 files changed, 75 insertions(+), 12 deletions(-) diff --git a/src/CycloneDX.Core/Models/Algorithms/AlgorithmProperties.cs b/src/CycloneDX.Core/Models/Algorithms/AlgorithmProperties.cs index 03e83245..0180b60d 100644 --- a/src/CycloneDX.Core/Models/Algorithms/AlgorithmProperties.cs +++ b/src/CycloneDX.Core/Models/Algorithms/AlgorithmProperties.cs @@ -16,6 +16,7 @@ // Copyright (c) OWASP Foundation. All Rights Reserved. using CycloneDX.Models; +using CycloneDX.Models.Vulnerabilities; using ProtoBuf; using System; using System.Collections.Generic; @@ -58,10 +59,12 @@ public bool ShouldSerializePrimitive_XML() [XmlElement("executionEnvironment")] [ProtoMember(4)] public ExecutionEnvironment? ExecutionEnvironment { get; set; } + public bool ShouldSerializeExecutionEnvironment() { return ExecutionEnvironment.HasValue && ExecutionEnvironment.Value != Models.ExecutionEnvironment.Null; } [XmlElement("implementationPlatform")] [ProtoMember(5)] public ImplementationPlatform? ImplementationPlatform { get; set; } + public bool ShouldSerializeImplementationPlatform() { return ImplementationPlatform.HasValue && ImplementationPlatform.Value != Models.ImplementationPlatform.Null; } [XmlElement("certificationLevel")] public List CertificationLevel { get; set; } diff --git a/src/CycloneDX.Core/Models/Crypto/CryptoProperties.cs b/src/CycloneDX.Core/Models/Crypto/CryptoProperties.cs index a5f717f4..a77ddf09 100644 --- a/src/CycloneDX.Core/Models/Crypto/CryptoProperties.cs +++ b/src/CycloneDX.Core/Models/Crypto/CryptoProperties.cs @@ -15,6 +15,7 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright (c) OWASP Foundation. All Rights Reserved. +using CycloneDX.Models.Vulnerabilities; using ProtoBuf; using System.Net.Sockets; using System.Text; @@ -28,8 +29,10 @@ namespace CycloneDX.Core.Models public class CryptoProperties { [XmlElement("assetType")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [ProtoMember(1)] public AssetType AssetType { get; set; } + public bool ShouldSerializeAssetType() { return AssetType != AssetType.Null; } [XmlElement("algorithmProperties")] [ProtoMember(2)] diff --git a/src/CycloneDX.Core/Models/Crypto/ProtocolProperties.cs b/src/CycloneDX.Core/Models/Crypto/ProtocolProperties.cs index 000713d7..311c27b7 100644 --- a/src/CycloneDX.Core/Models/Crypto/ProtocolProperties.cs +++ b/src/CycloneDX.Core/Models/Crypto/ProtocolProperties.cs @@ -15,6 +15,7 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright (c) OWASP Foundation. All Rights Reserved. +using CycloneDX.Models.Vulnerabilities; using ProtoBuf; using System.Collections.Generic; using System.Text.Json.Serialization; @@ -26,8 +27,10 @@ namespace CycloneDX.Core.Models public class ProtocolProperties { [XmlElement("type")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [ProtoMember(1)] public ProtocolType Type { get; set; } + public bool ShouldSerializeType() { return Type != ProtocolType.Null; } [XmlElement("version")] [ProtoMember(2)] diff --git a/src/CycloneDX.Core/Models/Crypto/RelatedCryptoMaterialProperties.cs b/src/CycloneDX.Core/Models/Crypto/RelatedCryptoMaterialProperties.cs index a61d7888..8955b256 100644 --- a/src/CycloneDX.Core/Models/Crypto/RelatedCryptoMaterialProperties.cs +++ b/src/CycloneDX.Core/Models/Crypto/RelatedCryptoMaterialProperties.cs @@ -15,12 +15,13 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright (c) OWASP Foundation. All Rights Reserved. +using CycloneDX.Models; +using CycloneDX.Models.Vulnerabilities; using ProtoBuf; using System; using System.Collections.Generic; using System.Text.Json.Serialization; using System.Xml.Serialization; -using CycloneDX.Models; namespace CycloneDX.Core.Models { @@ -28,16 +29,20 @@ namespace CycloneDX.Core.Models public class RelatedCryptoMaterialProperties { [XmlElement("type")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [ProtoMember(1)] public RelatedCryptoMaterialType Type { get; set; } + public bool ShouldSerializeType() { return Type != RelatedCryptoMaterialType.Null; } [XmlElement("id")] [ProtoMember(2)] public string Id { get; set; } [XmlElement("state")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [ProtoMember(3)] public KeyState State { get; set; } + public bool ShouldSerializeState() { return State != KeyState.Null; } [XmlElement("algorithmRef")] [ProtoMember(4)] diff --git a/src/CycloneDX.Core/Models/DataClassification.cs b/src/CycloneDX.Core/Models/DataClassification.cs index 1defc8a2..a8571729 100644 --- a/src/CycloneDX.Core/Models/DataClassification.cs +++ b/src/CycloneDX.Core/Models/DataClassification.cs @@ -15,10 +15,11 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright (c) OWASP Foundation. All Rights Reserved. +using CycloneDX.Models.Vulnerabilities; +using ProtoBuf; using System.Collections.Generic; using System.Text.Json.Serialization; using System.Xml.Serialization; -using ProtoBuf; namespace CycloneDX.Models { @@ -28,8 +29,10 @@ namespace CycloneDX.Models public class DataClassification { [XmlAttribute("flow")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [ProtoMember(1, IsRequired=true)] public DataFlowDirection Flow { get; set; } + public bool ShouldSerializeFlow() { return Flow != DataFlowDirection.Null; } [XmlText] [ProtoMember(2)] diff --git a/src/CycloneDX.Core/Models/DataFlow.cs b/src/CycloneDX.Core/Models/DataFlow.cs index 33ea874a..6cfe8fc3 100644 --- a/src/CycloneDX.Core/Models/DataFlow.cs +++ b/src/CycloneDX.Core/Models/DataFlow.cs @@ -15,11 +15,12 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright (c) OWASP Foundation. All Rights Reserved. +using CycloneDX.Models.Vulnerabilities; +using ProtoBuf; using System.Collections.Generic; using System.Linq; using System.Text.Json.Serialization; using System.Xml.Serialization; -using ProtoBuf; namespace CycloneDX.Models { @@ -29,8 +30,10 @@ public class DataFlow { [XmlIgnore] [JsonPropertyName("flow")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [ProtoMember(1, IsRequired=true)] public DataFlowDirection Flow { get; set; } + public bool ShouldSerializeFlow() { return Flow != DataFlowDirection.Null; } [XmlIgnore] [JsonPropertyName("classification")] diff --git a/src/CycloneDX.Core/Models/EnergyConsumption/Co2Measure.cs b/src/CycloneDX.Core/Models/EnergyConsumption/Co2Measure.cs index e70e6445..7059853c 100644 --- a/src/CycloneDX.Core/Models/EnergyConsumption/Co2Measure.cs +++ b/src/CycloneDX.Core/Models/EnergyConsumption/Co2Measure.cs @@ -15,7 +15,9 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright (c) OWASP Foundation. All Rights Reserved. +using CycloneDX.Models.Vulnerabilities; using ProtoBuf; +using System.Text.Json.Serialization; using System.Xml.Serialization; namespace CycloneDX.Models @@ -28,7 +30,9 @@ public class Co2Measure public float Value { get; set; } [XmlElement("unit")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [ProtoMember(2)] public CO2Unit Unit { get; set; } + public bool ShouldSerializeUnit() { return Unit != CO2Unit.Null; } } } diff --git a/src/CycloneDX.Core/Models/EnergyConsumption/EnergyConsumptions.cs b/src/CycloneDX.Core/Models/EnergyConsumption/EnergyConsumptions.cs index 3de190e1..795970fc 100644 --- a/src/CycloneDX.Core/Models/EnergyConsumption/EnergyConsumptions.cs +++ b/src/CycloneDX.Core/Models/EnergyConsumption/EnergyConsumptions.cs @@ -15,10 +15,12 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright (c) OWASP Foundation. All Rights Reserved. +using CycloneDX.Models.Vulnerabilities; using ProtoBuf; using System; using System.Collections.Generic; using System.Text; +using System.Text.Json.Serialization; using System.Xml.Serialization; namespace CycloneDX.Models @@ -27,8 +29,10 @@ namespace CycloneDX.Models public class EnergyConsumption { [XmlElement("activity")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [ProtoMember(1)] public ActivityType Activity { get; set; } + public bool ShouldSerializeActivity() { return Activity != ActivityType.Null; } [XmlElement("energyProviders")] [ProtoMember(2)] diff --git a/src/CycloneDX.Core/Models/EnergyConsumption/EnergyMeasure.cs b/src/CycloneDX.Core/Models/EnergyConsumption/EnergyMeasure.cs index 644301b2..16e57bb1 100644 --- a/src/CycloneDX.Core/Models/EnergyConsumption/EnergyMeasure.cs +++ b/src/CycloneDX.Core/Models/EnergyConsumption/EnergyMeasure.cs @@ -15,7 +15,9 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright (c) OWASP Foundation. All Rights Reserved. +using CycloneDX.Models.Vulnerabilities; using ProtoBuf; +using System.Text.Json.Serialization; using System.Xml.Serialization; namespace CycloneDX.Models @@ -28,7 +30,9 @@ public class EnergyMeasure public float Value { get; set; } [XmlElement("unit")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [ProtoMember(2)] public EnergyUnit Unit { get; set; } + public bool ShouldSerializeUnit() { return Unit != EnergyUnit.Null; } } } diff --git a/src/CycloneDX.Core/Models/EnergyConsumption/EnergyProvider.cs b/src/CycloneDX.Core/Models/EnergyConsumption/EnergyProvider.cs index a6bb31ea..1e6d0057 100644 --- a/src/CycloneDX.Core/Models/EnergyConsumption/EnergyProvider.cs +++ b/src/CycloneDX.Core/Models/EnergyConsumption/EnergyProvider.cs @@ -15,8 +15,10 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright (c) OWASP Foundation. All Rights Reserved. +using CycloneDX.Models.Vulnerabilities; using ProtoBuf; using System.Collections.Generic; +using System.Text.Json.Serialization; using System.Xml.Serialization; namespace CycloneDX.Models @@ -33,8 +35,10 @@ public class EnergyProvider public OrganizationalEntity Organization { get; set; } [XmlElement("energySource")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [ProtoMember(4)] public EnergySource EnergySource { get; set; } + public bool ShouldSerializeEnergySource() { return EnergySource != EnergySource.Null; } [XmlElement("energyProvided")] [ProtoMember(5)] diff --git a/src/CycloneDX.Core/Models/EvidenceIdentity.cs b/src/CycloneDX.Core/Models/EvidenceIdentity.cs index 60831c5c..094cbd86 100644 --- a/src/CycloneDX.Core/Models/EvidenceIdentity.cs +++ b/src/CycloneDX.Core/Models/EvidenceIdentity.cs @@ -15,6 +15,8 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright (c) OWASP Foundation. All Rights Reserved. +using CycloneDX.Models.Vulnerabilities; +using ProtoBuf; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -23,7 +25,6 @@ using System.Text.Json.Serialization; using System.Xml; using System.Xml.Serialization; -using ProtoBuf; namespace CycloneDX.Models { @@ -58,8 +59,10 @@ public enum EvidenceFieldType } [XmlElement("field")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [ProtoMember(1)] public EvidenceFieldType Field { get; set; } + public bool ShouldSerializeField() { return Field != EvidenceFieldType.Null; } [XmlElement("confidence")] [ProtoMember(2)] diff --git a/src/CycloneDX.Core/Models/Hash.cs b/src/CycloneDX.Core/Models/Hash.cs index ca7b0754..0578bc48 100644 --- a/src/CycloneDX.Core/Models/Hash.cs +++ b/src/CycloneDX.Core/Models/Hash.cs @@ -15,8 +15,10 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright (c) OWASP Foundation. All Rights Reserved. -using System.Xml.Serialization; +using CycloneDX.Models.Vulnerabilities; using ProtoBuf; +using System.Text.Json.Serialization; +using System.Xml.Serialization; namespace CycloneDX.Models { @@ -60,9 +62,11 @@ public enum HashAlgorithm } [XmlAttribute("alg")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [ProtoMember(1, IsRequired=true)] public HashAlgorithm Alg { get; set; } - + public bool ShouldSerializeAlg() { return Alg != HashAlgorithm.Null; } + [XmlText] [ProtoMember(2)] public string Content { get; set; } diff --git a/src/CycloneDX.Core/Models/Issue.cs b/src/CycloneDX.Core/Models/Issue.cs index d8f3f584..cdea60d1 100644 --- a/src/CycloneDX.Core/Models/Issue.cs +++ b/src/CycloneDX.Core/Models/Issue.cs @@ -15,9 +15,11 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright (c) OWASP Foundation. All Rights Reserved. +using CycloneDX.Models.Vulnerabilities; +using ProtoBuf; using System.Collections.Generic; +using System.Text.Json.Serialization; using System.Xml.Serialization; -using ProtoBuf; namespace CycloneDX.Models { @@ -38,8 +40,10 @@ public enum IssueClassification } [XmlAttribute("type")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [ProtoMember(1, IsRequired=true)] public IssueClassification Type { get; set; } + public bool ShouldSerializeType() { return Type != IssueClassification.Null; } [XmlElement("id")] [ProtoMember(2)] diff --git a/src/CycloneDX.Core/Models/LicenseChoice.cs b/src/CycloneDX.Core/Models/LicenseChoice.cs index 31518f25..b30ee20d 100644 --- a/src/CycloneDX.Core/Models/LicenseChoice.cs +++ b/src/CycloneDX.Core/Models/LicenseChoice.cs @@ -47,7 +47,7 @@ public class LicenseChoice [XmlAttribute("acknowledgement")] [ProtoMember(3)] public LicenseAcknowledgementEnumeration? Acknowledgement { get; set; } - public bool ShouldSerializeAcknowledgement() { return Acknowledgement.HasValue; } + public bool ShouldSerializeAcknowledgement() { return Acknowledgement.HasValue && Acknowledgement.Value != LicenseAcknowledgementEnumeration.Null; } [JsonPropertyName("expressionDetails")] [XmlIgnore] diff --git a/src/CycloneDX.Core/Models/Patch.cs b/src/CycloneDX.Core/Models/Patch.cs index cdc5e2cf..5e475b5d 100644 --- a/src/CycloneDX.Core/Models/Patch.cs +++ b/src/CycloneDX.Core/Models/Patch.cs @@ -15,9 +15,11 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright (c) OWASP Foundation. All Rights Reserved. +using CycloneDX.Models.Vulnerabilities; +using ProtoBuf; using System.Collections.Generic; +using System.Text.Json.Serialization; using System.Xml.Serialization; -using ProtoBuf; namespace CycloneDX.Models { @@ -40,8 +42,10 @@ public enum PatchClassification } [XmlAttribute("type")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [ProtoMember(1, IsRequired=true)] public PatchClassification Type { get; set; } + public bool ShouldSerializeType() { return Type != PatchClassification.Null; } [XmlElement("diff")] [ProtoMember(2)] diff --git a/src/CycloneDX.Core/Models/Patent.cs b/src/CycloneDX.Core/Models/Patent.cs index 1bb17599..a79e1489 100644 --- a/src/CycloneDX.Core/Models/Patent.cs +++ b/src/CycloneDX.Core/Models/Patent.cs @@ -15,12 +15,13 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright (c) OWASP Foundation. All Rights Reserved. +using CycloneDX.Models.Vulnerabilities; +using ProtoBuf; using System; using System.Collections.Generic; using System.Globalization; using System.Text.Json.Serialization; using System.Xml.Serialization; -using ProtoBuf; namespace CycloneDX.Models { @@ -163,8 +164,10 @@ public string PatentExpirationDate public bool ShouldSerializePatentExpirationDate() { return PatentExpirationDate != null; } [XmlElement("patentLegalStatus")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [ProtoMember(12)] public PatentLegalStatus PatentLegalStatus { get; set; } + public bool ShouldSerializePatentLegalStatus() { return PatentLegalStatus != PatentLegalStatus.Null; } [XmlElement("patentAssignee")] [ProtoMember(13)] diff --git a/src/CycloneDX.Core/Models/PatentAssertion.cs b/src/CycloneDX.Core/Models/PatentAssertion.cs index 587f7d0a..2da9ca03 100644 --- a/src/CycloneDX.Core/Models/PatentAssertion.cs +++ b/src/CycloneDX.Core/Models/PatentAssertion.cs @@ -15,10 +15,11 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright (c) OWASP Foundation. All Rights Reserved. +using CycloneDX.Models.Vulnerabilities; +using ProtoBuf; using System.Collections.Generic; using System.Text.Json.Serialization; using System.Xml.Serialization; -using ProtoBuf; namespace CycloneDX.Models { @@ -31,8 +32,10 @@ public class PatentAssertion public string BomRef { get; set; } [XmlElement("assertionType")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [ProtoMember(2)] public PatentAssertionType AssertionType { get; set; } + public bool ShouldSerializeAssertionType() { return AssertionType != PatentAssertionType.Null; } [XmlArray("patentRefs")] [XmlArrayItem("bom-ref")] diff --git a/src/CycloneDX.Core/Models/Vulnerabilities/Analysis.cs b/src/CycloneDX.Core/Models/Vulnerabilities/Analysis.cs index c0411f46..d65384f5 100644 --- a/src/CycloneDX.Core/Models/Vulnerabilities/Analysis.cs +++ b/src/CycloneDX.Core/Models/Vulnerabilities/Analysis.cs @@ -15,10 +15,12 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright (c) OWASP Foundation. All Rights Reserved. +using CycloneDX.Core.Models; +using ProtoBuf; using System; using System.Collections.Generic; +using System.Text.Json.Serialization; using System.Xml.Serialization; -using ProtoBuf; namespace CycloneDX.Models.Vulnerabilities { @@ -26,12 +28,16 @@ namespace CycloneDX.Models.Vulnerabilities public class Analysis { [XmlElement("state")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [ProtoMember(1)] public ImpactAnalysisState State { get; set; } + public bool ShouldSerializeState() { return State != ImpactAnalysisState.Null; } [XmlElement("justification")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [ProtoMember(2)] public ImpactAnalysisJustification Justification { get; set; } + public bool ShouldSerializeJustification() { return Justification != ImpactAnalysisJustification.Null; } [XmlArray("responses")] [XmlArrayItem("response")]