Skip to content

Commit 4b37b9e

Browse files
authored
Fix Data Member Attribute json Serialized Model Casing Applied[Azure#212] (Azure#263)
1 parent f0c52d2 commit 4b37b9e

File tree

6 files changed

+179
-3
lines changed

6 files changed

+179
-3
lines changed

src/Microsoft.Azure.WebJobs.Extensions.OpenApi.Core/Extensions/PropertyInfoExtensions.cs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
using System.Reflection;
2-
2+
using System.Runtime.Serialization;
33
using Newtonsoft.Json;
44
using Newtonsoft.Json.Serialization;
55

@@ -23,11 +23,23 @@ public static bool HasJsonPropertyAttribute(this PropertyInfo element)
2323
}
2424

2525
/// <summary>
26-
/// Gets the name from <see cref="JsonPropertyAttribute"/> instance.
26+
/// Checks whether the given <see cref="PropertyInfo"/> object has <see cref="DataMemberAttribute"/> or not.
27+
/// </summary>
28+
/// <param name="element"><see cref="PropertyInfo"/> instance.</param>
29+
/// <returns>Returns <c>True</c>, if the given <see cref="PropertyInfo"/> object has <see cref="DataMemberAttribute"/>; otherwise, returns <c>False</c>.</returns>
30+
public static bool HasDataMemberAttribute(this PropertyInfo element)
31+
{
32+
var exists = element.ExistsCustomAttribute<DataMemberAttribute>();
33+
34+
return exists;
35+
}
36+
37+
/// <summary>
38+
/// Gets the name from <see cref="JsonPropertyAttribute"/> or <see cref="DataMemberAttribute"/> instance.
2739
/// </summary>
2840
/// <param name="element"><see cref="PropertyInfo"/> instance.</param>
2941
/// <param name="namingStrategy"><see cref="NamingStrategy"/> instance.</param>
30-
/// <returns>Returns the name from <see cref="JsonPropertyAttribute"/> instance.</returns>
42+
/// <returns>Returns the name from <see cref="JsonPropertyAttribute"/> or <see cref="DataMemberAttribute"/> instance.</returns>
3143
public static string GetJsonPropertyName(this PropertyInfo element, NamingStrategy namingStrategy = null)
3244
{
3345
if (namingStrategy.IsNullOrDefault())
@@ -43,6 +55,14 @@ public static string GetJsonPropertyName(this PropertyInfo element, NamingStrate
4355

4456
}
4557

58+
if (element.HasDataMemberAttribute())
59+
{
60+
var name = element.GetCustomAttribute<DataMemberAttribute>().Name ?? namingStrategy.GetPropertyName(element.Name, hasSpecifiedName: false);
61+
62+
return name;
63+
64+
}
65+
4666
return namingStrategy.GetPropertyName(element.Name, hasSpecifiedName: false);
4767
}
4868
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
using System.Net.Http;
2+
using System.Threading.Tasks;
3+
4+
using FluentAssertions;
5+
6+
using Microsoft.VisualStudio.TestTools.UnitTesting;
7+
8+
using Newtonsoft.Json;
9+
using Newtonsoft.Json.Linq;
10+
11+
namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Document.Tests
12+
{
13+
[TestClass]
14+
[TestCategory(Constants.TestCategory)]
15+
public class Get_ApplicationJson_JsonProperty_Tests
16+
{
17+
private static HttpClient http = new HttpClient();
18+
19+
private JObject _doc;
20+
21+
[TestInitialize]
22+
public async Task Init()
23+
{
24+
var json = await http.GetStringAsync(Constants.OpenApiDocEndpoint).ConfigureAwait(false);
25+
this._doc = JsonConvert.DeserializeObject<JObject>(json);
26+
}
27+
28+
[DataTestMethod]
29+
[DataRow("/get-applicationjson-jsonproperty", "get", "200")]
30+
public void Given_OpenApiDocument_Then_It_Should_Return_OperationResponse(string path, string operationType, string responseCode)
31+
{
32+
var responses = this._doc["paths"][path][operationType]["responses"];
33+
34+
responses[responseCode].Should().NotBeNull();
35+
}
36+
37+
[DataTestMethod]
38+
[DataRow("/get-applicationjson-jsonproperty", "get", "200", "application/json")]
39+
public void Given_OpenApiDocument_Then_It_Should_Return_OperationResponseContentType(string path, string operationType, string responseCode, string contentType)
40+
{
41+
var content = this._doc["paths"][path][operationType]["responses"][responseCode]["content"];
42+
43+
content[contentType].Should().NotBeNull();
44+
}
45+
46+
[DataTestMethod]
47+
[DataRow("/get-applicationjson-jsonproperty", "get", "200", "application/json", "jsonPropertyObjectModel")]
48+
public void Given_OpenApiDocument_Then_It_Should_Return_OperationResponseContentTypeSchema(string path, string operationType, string responseCode, string contentType, string reference)
49+
{
50+
var content = this._doc["paths"][path][operationType]["responses"][responseCode]["content"];
51+
52+
var @ref = content[contentType]["schema"]["$ref"];
53+
54+
@ref.Value<string>().Should().Be($"#/components/schemas/{reference}");
55+
}
56+
57+
[DataTestMethod]
58+
[DataRow("jsonPropertyObjectModel", "object")]
59+
public void Given_OpenApiDocument_Then_It_Should_Return_ComponentSchema(string @ref, string refType)
60+
{
61+
var schemas = this._doc["components"]["schemas"];
62+
63+
var schema = schemas[@ref];
64+
65+
schema.Should().NotBeNull();
66+
schema.Value<string>("type").Should().Be(refType);
67+
}
68+
69+
[DataTestMethod]
70+
[DataRow("jsonPropertyObjectModel", "object", "memBer1", "string", null)]
71+
[DataRow("jsonPropertyObjectModel", "object", "MEMBER2", "integer", "int32")]
72+
[DataRow("jsonPropertyObjectModel", "object", "MeMBer3", "string", "date-time")]
73+
[DataRow("jsonPropertyObjectModel", "object", "member4", "boolean", null)]
74+
[DataRow("jsonPropertyObjectModel", "object", "MembeR5", "number", "double")]
75+
public void Given_OpenApiDocument_Then_It_Should_Return_ComponentSchemaProperty(string @ref, string refType, string propertyName, string propertyType, string propertyFormat)
76+
{
77+
var properties = this._doc["components"]["schemas"][@ref]["properties"];
78+
79+
var value = properties[propertyName];
80+
81+
value.Should().NotBeNull();
82+
value.Value<string>("type").Should().Be(propertyType);
83+
value.Value<string>("format").Should().Be(propertyFormat);
84+
}
85+
}
86+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System.Net;
2+
using System.Threading.Tasks;
3+
4+
using Microsoft.AspNetCore.Http;
5+
using Microsoft.AspNetCore.Mvc;
6+
using Microsoft.Azure.WebJobs.Extensions.Http;
7+
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Attributes;
8+
using Microsoft.Azure.WebJobs.Extensions.OpenApi.TestApp.Models;
9+
using Microsoft.Extensions.Logging;
10+
using Microsoft.OpenApi.Models;
11+
12+
namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.TestApp
13+
{
14+
public static class Get_ApplicationJson_JsonPropertyObject_HttpTrigger
15+
{
16+
[FunctionName(nameof(Get_ApplicationJson_JsonPropertyObject_HttpTrigger))]
17+
[OpenApiOperation(operationId: nameof(Get_ApplicationJson_JsonPropertyObject_HttpTrigger.Get_ApplicationJson_JsonPropertyObject), tags: new[] { "jsonproperty" })]
18+
[OpenApiResponseWithBody(statusCode: HttpStatusCode.OK, contentType: "application/json", bodyType: typeof(JsonPropertyObjectModel), Description = "The OK response")]
19+
public static async Task<IActionResult> Get_ApplicationJson_JsonPropertyObject(
20+
[HttpTrigger(AuthorizationLevel.Anonymous, "GET", Route = "get-applicationjson-jsonproperty")] HttpRequest req,
21+
ILogger log)
22+
{
23+
var result = new OkResult();
24+
25+
return await Task.FromResult(result).ConfigureAwait(false);
26+
}
27+
}
28+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using Newtonsoft.Json;
2+
using System;
3+
using System.Runtime.Serialization;
4+
5+
namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.TestApp.Models
6+
{
7+
public class JsonPropertyObjectModel
8+
{
9+
[DataMember(Name = "memBer1")]
10+
public string DataMemberValue1 { get; set; }
11+
12+
[DataMember(Name = "MEMBER2")]
13+
public int DataMemberValue2 { get; set; }
14+
15+
[DataMember(Name = "MeMBer3")]
16+
public DateTime DataMemberValue3 { get; set; }
17+
18+
[DataMember(Name = "member4")]
19+
public bool DataMemberValue4 { get; set; }
20+
21+
[DataMember(Name = "MembeR5")]
22+
public double DataMemberValue5 { get; set; }
23+
24+
}
25+
}

test/Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Tests.Fakes/FakeModel.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Newtonsoft.Json;
2+
using System.Runtime.Serialization;
23

34
namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Tests.Fakes
45
{
@@ -25,6 +26,9 @@ public class FakeModel
2526
[JsonProperty]
2627
public string FakePropertyNoAnnotation { get; set; }
2728

29+
[DataMember(Name = "anotherDataMemberFakeProperty")]
30+
public string DataMemberFakeProperty { get; set; }
31+
2832
public object FakeObject { get; set; }
2933

3034
/// <summary>

test/Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Tests/Extensions/PropertyInfoExtensionsTests.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,19 @@ public void Given_Property_When_GetJsonPropertyName_Invoked_Then_It_Should_Retur
4141
result.Should().Be(jsonPropertyName);
4242
}
4343

44+
[TestMethod]
45+
public void Given_Property_When_GetDataMemberName_Invoked_Then_It_Should_Return_DataMemberName()
46+
{
47+
var name = "DataMemberFakeProperty";
48+
var jsonPropertyName = "anotherDataMemberFakeProperty";
49+
var property = typeof(FakeModel).GetProperty(name, BindingFlags.Public | BindingFlags.Instance);
50+
var namingStrategy = new DefaultNamingStrategy();
51+
52+
var result = PropertyInfoExtensions.GetJsonPropertyName(property, namingStrategy);
53+
54+
result.Should().Be(jsonPropertyName);
55+
}
56+
4457
[TestMethod]
4558
public void Given_Property_When_GetJsonPropertyName_IsEmpty_Then_It_Should_Return_ElementName()
4659
{

0 commit comments

Comments
 (0)