Skip to content
This repository has been archived by the owner on Jul 9, 2024. It is now read-only.

Commit

Permalink
Add support for enum member attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
vadrsa committed Mar 30, 2023
1 parent e26135c commit 124139b
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 2 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- Fixes a bug where EnumMember attribute was not taken into account during serialization/deserialization

## [1.0.3] - 2023-03-15

### Changed
Expand Down Expand Up @@ -94,3 +96,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Initial Nuget release

Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class JsonParseNodeTests
" ],\r\n" +
" \"displayName\": \"Megan Bowen\",\r\n" +
" \"numbers\":\"one,two,thirtytwo\"," +
" \"testNamingEnum\":\"Item2:SubItem1\"," +
" \"givenName\": \"Megan\",\r\n" +
" \"accountEnabled\": true,\r\n" +
" \"createdDateTime\": \"2017 -07-29T03:07:25Z\",\r\n" +
Expand Down Expand Up @@ -53,6 +54,7 @@ public void GetsEntityValueFromJson()
Assert.Equal("Auditor", testEntity.AdditionalData["jobTitle"]);
Assert.Equal("48d31887-5fad-4d73-a9f5-3c356e68a038", testEntity.Id);
Assert.Equal(TestEnum.One | TestEnum.Two, testEntity.Numbers ); // Unknown enum value is not included
Assert.Equal(TestNamingEnum.Item2SubItem1, testEntity.TestNamingEnum ); // correct value is chosen
Assert.Equal(TimeSpan.FromHours(1), testEntity.WorkDuration); // Parses timespan values
Assert.Equal(new Time(8,0,0).ToString(),testEntity.StartWorkTime.ToString());// Parses time values
Assert.Equal(new Time(17, 0, 0).ToString(), testEntity.EndWorkTime.ToString());// Parses time values
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ public void WritesSampleCollectionOfObjectValues()
{
Id = "48d31887-5fad-4d73-a9f5-3c356e68a038",
Numbers = TestEnum.One | TestEnum.Two,
TestNamingEnum = TestNamingEnum.Item2SubItem1,
AdditionalData = new Dictionary<string, object>
{
{"mobilePhone",null}, // write null value
Expand All @@ -136,6 +137,7 @@ public void WritesSampleCollectionOfObjectValues()
var expectedString = "[{" +
"\"id\":\"48d31887-5fad-4d73-a9f5-3c356e68a038\"," +
"\"numbers\":\"one,two\"," +
"\"testNamingEnum\":\"item2:SubItem1\"," +
"\"mobilePhone\":null," +
"\"accountEnabled\":false," +
"\"jobTitle\":\"Author\"," +
Expand Down
4 changes: 4 additions & 0 deletions Microsoft.Kiota.Serialization.Json.Tests/Mocks/TestEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ public class TestEntity : IParsable, IAdditionalDataHolder
/// <summary>Read-only.</summary>
public TestEnum? Numbers { get; set; }
/// <summary>Read-only.</summary>
public TestNamingEnum? TestNamingEnum { get; set; }
/// <summary>Read-only.</summary>
public TimeSpan? WorkDuration { get; set; }
/// <summary>Read-only.</summary>
public Date? BirthDay { get; set; }
Expand All @@ -40,6 +42,7 @@ public IDictionary<string, Action<IParseNode>> GetFieldDeserializers()
return new Dictionary<string, Action<IParseNode>> {
{"id", n => { Id = n.GetStringValue(); } },
{"numbers", n => { Numbers = n.GetEnumValue<TestEnum>(); } },
{"testNamingEnum", n => { TestNamingEnum = n.GetEnumValue<TestNamingEnum>(); } },
{"createdDateTime", n => { CreatedDateTime = n.GetDateTimeOffsetValue(); } },
{"officeLocation", n => { OfficeLocation = n.GetStringValue(); } },
{"workDuration", n => { WorkDuration = n.GetTimeSpanValue(); } },
Expand All @@ -57,6 +60,7 @@ public void Serialize(ISerializationWriter writer)
_ = writer ?? throw new ArgumentNullException(nameof(writer));
writer.WriteStringValue("id", Id);
writer.WriteEnumValue<TestEnum>("numbers",Numbers);
writer.WriteEnumValue<TestNamingEnum>("testNamingEnum",TestNamingEnum);
writer.WriteDateTimeOffsetValue("createdDateTime", CreatedDateTime);
writer.WriteStringValue("officeLocation", OfficeLocation);
writer.WriteTimeSpanValue("workDuration", WorkDuration);
Expand Down
13 changes: 13 additions & 0 deletions Microsoft.Kiota.Serialization.Json.Tests/Mocks/TestNamingEnum.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Runtime.Serialization;

namespace Microsoft.Kiota.Serialization.Json.Tests.Mocks
{
public enum TestNamingEnum
{
Item1,
[EnumMember(Value = "Item2:SubItem1")]
Item2SubItem1,
[EnumMember(Value = "Item3:SubItem1")]
Item3SubItem1
}
}
15 changes: 15 additions & 0 deletions src/JsonParseNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text.Json;
using Microsoft.Kiota.Abstractions.Serialization;
using Microsoft.Kiota.Abstractions;
Expand Down Expand Up @@ -152,6 +153,7 @@ public JsonParseNode(JsonElement node)
{
var rawValue = _jsonNode.GetString();
if(string.IsNullOrEmpty(rawValue)) return null;
rawValue = ToEnumRawName<T>(rawValue!);
if(typeof(T).GetCustomAttributes<FlagsAttribute>().Any())
{
return (T)(object)rawValue!
Expand Down Expand Up @@ -384,5 +386,18 @@ private void AssignFieldValues<T>(T item) where T : IParsable

return default;
}

private string ToEnumRawName<T>(string value) where T : struct, Enum
{
var type = typeof(T);
var members = type.GetMembers();
foreach(var member in members)
{
var attribute = member.GetCustomAttribute<EnumMemberAttribute>();
if(attribute != null && attribute.Value == value) return member.Name;
}

return value;
}
}
}
15 changes: 13 additions & 2 deletions src/JsonSerializationWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Microsoft.Kiota.Abstractions.Serialization;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Serialization;
using Microsoft.Kiota.Abstractions.Extensions;
using Microsoft.Kiota.Abstractions;
using System.Xml;
Expand Down Expand Up @@ -241,10 +242,10 @@ public void WriteEnumValue<T>(string? key, T? value) where T : struct, Enum
writer.WriteStringValue(Enum.GetValues(typeof(T))
.Cast<T>()
.Where(x => value.Value.HasFlag(x))
.Select(x => Enum.GetName(typeof(T),x))
.Select(GetEnumName)
.Select(x => x.ToFirstCharacterLowerCase())
.Aggregate((x, y) => $"{x},{y}"));
else writer.WriteStringValue(value.Value.ToString().ToFirstCharacterLowerCase());
else writer.WriteStringValue(GetEnumName(value.Value).ToFirstCharacterLowerCase());
}
}

Expand Down Expand Up @@ -433,5 +434,15 @@ public void Dispose()
writer.Dispose();
GC.SuppressFinalize(this);
}

private string GetEnumName<T>(T value) where T : struct, Enum
{
var type = typeof(T);
var name = Enum.GetName(type, value)!;
var attribute = type.GetMember(name)[0].GetCustomAttribute<EnumMemberAttribute>();
if (attribute != null) name = attribute.Value;

return name;
}
}
}

0 comments on commit 124139b

Please sign in to comment.