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

Commit

Permalink
Merge pull request #138 from microsoft/hotfix/down-cast-fix
Browse files Browse the repository at this point in the history
hotfix/down cast fix
  • Loading branch information
baywet authored Oct 23, 2023
2 parents dce2652 + 426ad11 commit a4ce0b2
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 12 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

## [1.1.1] - 2023-10-23

### Changed

- Fixed a bug where deserialization of downcast type fields would be ignored.

## [1.1.0] - 2023-10-23

### Added
Expand Down
41 changes: 40 additions & 1 deletion Microsoft.Kiota.Serialization.Json.Tests/JsonParseNodeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,33 @@ public class JsonParseNodeTests
" \"birthDay\": \"2017-09-04\",\r\n" +
" \"id\": \"48d31887-5fad-4d73-a9f5-3c356e68a038\"\r\n" +
"}";
private const string TestStudentJson = "{\r\n" +
" \"@odata.context\": \"https://graph.microsoft.com/v1.0/$metadata#users/$entity\",\r\n" +
" \"@odata.type\": \"microsoft.graph.student\",\r\n" +
" \"@odata.id\": \"https://graph.microsoft.com/v2/dcd219dd-bc68-4b9b-bf0b-4a33a796be35/directoryObjects/48d31887-5fad-4d73-a9f5-3c356e68a038/Microsoft.DirectoryServices.User\",\r\n" +
" \"businessPhones\": [\r\n" +
" \"+1 412 555 0109\"\r\n" +
" ],\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" +
" \"jobTitle\": \"Auditor\",\r\n" +
" \"mail\": \"[email protected]\",\r\n" +
" \"mobilePhone\": null,\r\n" +
" \"officeLocation\": null,\r\n" +
" \"preferredLanguage\": \"en-US\",\r\n" +
" \"surname\": \"Bowen\",\r\n" +
" \"workDuration\": \"PT1H\",\r\n" +
" \"startWorkTime\": \"08:00:00.0000000\",\r\n" +
" \"endWorkTime\": \"17:00:00.0000000\",\r\n" +
" \"userPrincipalName\": \"[email protected]\",\r\n" +
" \"birthDay\": \"2017-09-04\",\r\n" +
" \"enrolmentDate\": \"2017-09-04\",\r\n" +
" \"id\": \"48d31887-5fad-4d73-a9f5-3c356e68a038\"\r\n" +
"}";

private static readonly string TestUserCollectionString = $"[{TestUserJson}]";

Expand All @@ -44,7 +71,7 @@ public void GetsEntityValueFromJson()
using var jsonDocument = JsonDocument.Parse(TestUserJson);
var jsonParseNode = new JsonParseNode(jsonDocument.RootElement);
// Act
var testEntity = jsonParseNode.GetObjectValue<TestEntity>(x => new TestEntity());
var testEntity = jsonParseNode.GetObjectValue(TestEntity.CreateFromDiscriminator);
// Assert
Assert.NotNull(testEntity);
Assert.Null(testEntity.OfficeLocation);
Expand All @@ -60,6 +87,18 @@ public void GetsEntityValueFromJson()
Assert.Equal(new Time(17, 0, 0).ToString(), testEntity.EndWorkTime.ToString());// Parses time values
Assert.Equal(new Date(2017,9,4).ToString(), testEntity.BirthDay.ToString());// Parses date values
}
[Fact]
public void GetsFieldFromDerivedType()
{
// Arrange
using var jsonDocument = JsonDocument.Parse(TestStudentJson);
var jsonParseNode = new JsonParseNode(jsonDocument.RootElement);
// Act
var testEntity = jsonParseNode.GetObjectValue(TestEntity.CreateFromDiscriminator) as DerivedTestEntity;
// Assert
Assert.NotNull(testEntity);
Assert.NotNull(testEntity.EnrolmentDate);
}

[Fact]
public void GetCollectionOfObjectValuesFromJson()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using Microsoft.Kiota.Abstractions;
using Microsoft.Kiota.Abstractions.Serialization;

namespace Microsoft.Kiota.Serialization.Json.Tests.Mocks
{
public class DerivedTestEntity : TestEntity
{
/// <summary>
/// Date enrolled in primary school
/// </summary>
public Date? EnrolmentDate { get; set; }
public override IDictionary<string, Action<IParseNode>> GetFieldDeserializers()
{
var parentDeserializers = base.GetFieldDeserializers();
parentDeserializers.Add("enrolmentDate", n => { EnrolmentDate = n.GetDateValue(); });
return parentDeserializers;
}
public override void Serialize(ISerializationWriter writer)
{
base.Serialize(writer);
writer.WriteDateValue("enrolmentDate", EnrolmentDate.Value);
}
}
}
13 changes: 10 additions & 3 deletions Microsoft.Kiota.Serialization.Json.Tests/Mocks/TestEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public TestEntity()
/// <summary>
/// The deserialization information for the current model
/// </summary>
public IDictionary<string, Action<IParseNode>> GetFieldDeserializers()
public virtual IDictionary<string, Action<IParseNode>> GetFieldDeserializers()
{
return new Dictionary<string, Action<IParseNode>> {
{"id", n => { Id = n.GetStringValue(); } },
Expand All @@ -55,7 +55,7 @@ public IDictionary<string, Action<IParseNode>> GetFieldDeserializers()
/// Serializes information the current object
/// <param name="writer">Serialization writer to use to serialize this model</param>
/// </summary>
public void Serialize(ISerializationWriter writer)
public virtual void Serialize(ISerializationWriter writer)
{
_ = writer ?? throw new ArgumentNullException(nameof(writer));
writer.WriteStringValue("id", Id);
Expand All @@ -70,7 +70,14 @@ public void Serialize(ISerializationWriter writer)
writer.WriteAdditionalData(AdditionalData);
}
public static TestEntity CreateFromDiscriminator(IParseNode parseNode) {
return new TestEntity();
var discriminatorValue = parseNode.GetChildNode("@odata.type")?.GetStringValue();
return discriminatorValue switch
{
"microsoft.graph.user" => new TestEntity(),
"microsoft.graph.group" => new TestEntity(),
"microsoft.graph.student" => new DerivedTestEntity(),
_ => new TestEntity(),
};
}
}
}
8 changes: 1 addition & 7 deletions src/JsonParseNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -312,11 +312,7 @@ public T GetObjectValue<T>(ParsableFactory<T> factory) where T : IParsable
OnAfterAssignFieldValues?.Invoke(item);
return item;
}
#if NET5_0_OR_GREATER
private void AssignFieldValues<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>(T item) where T : IParsable
#else
private void AssignFieldValues<T>(T item) where T : IParsable
#endif
{
if(_jsonNode.ValueKind != JsonValueKind.Object) return;
IDictionary<string, object>? itemAdditionalData = null;
Expand All @@ -325,9 +321,7 @@ private void AssignFieldValues<T>(T item) where T : IParsable
holder.AdditionalData ??= new Dictionary<string, object>();
itemAdditionalData = holder.AdditionalData;
}
//When targeting maccatalyst, new keyword for hiding an existing member is not being respected, returning only id and odata type
//the below line fixes the issue
var fieldDeserializers = typeof(T).GetMethod("GetFieldDeserializers")?.Invoke(item, null) is IDictionary<string, Action<IParseNode>> result ? result : item.GetFieldDeserializers();
var fieldDeserializers = item.GetFieldDeserializers();

foreach(var fieldValue in _jsonNode.EnumerateObject())
{
Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.Kiota.Serialization.Json.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<PackageProjectUrl>https://aka.ms/kiota/docs</PackageProjectUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<Deterministic>true</Deterministic>
<VersionPrefix>1.1.0</VersionPrefix>
<VersionPrefix>1.1.1</VersionPrefix>
<VersionSuffix></VersionSuffix>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
Expand Down

0 comments on commit a4ce0b2

Please sign in to comment.