Skip to content

Commit 4c9d54e

Browse files
authored
add TimeSpanObjectTypeVisitor (#524)
1 parent 3828893 commit 4c9d54e

File tree

11 files changed

+278
-0
lines changed

11 files changed

+278
-0
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ public static string ToDataType(this Type type)
8888
{
8989
return "string";
9090
}
91+
else if (type == typeof(TimeSpan))
92+
{
93+
return "string";
94+
}
9195
else
9296
{
9397
return "object";
@@ -161,6 +165,10 @@ public static string ToDataFormat(this Type type)
161165
{
162166
return "date-time";
163167
}
168+
else if (type == typeof(TimeSpan))
169+
{
170+
return "timespan";
171+
}
164172
else
165173
{
166174
return null;

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public static bool IsSimpleType(this Type type)
3636
case TypeCode.DateTime:
3737
case TypeCode.String:
3838
case TypeCode.Object when type == typeof(Guid):
39+
case TypeCode.Object when type == typeof(TimeSpan):
3940
case TypeCode.Object when type == typeof(DateTime):
4041
case TypeCode.Object when type == typeof(DateTimeOffset):
4142
return true;
@@ -85,6 +86,7 @@ public static bool IsJObjectType(this Type type)
8586
typeof(Guid),
8687
typeof(DateTime),
8788
typeof(DateTimeOffset),
89+
typeof(TimeSpan),
8890
typeof(Uri),
8991
typeof(object),
9092
};

src/Microsoft.Azure.WebJobs.Extensions.OpenApi.Core/Visitors/ObjectTypeVisitor.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public class ObjectTypeVisitor : TypeVisitor
2424
{
2525
typeof(Guid),
2626
typeof(DateTime),
27+
typeof(TimeSpan),
2728
typeof(DateTimeOffset),
2829
typeof(Uri),
2930
typeof(Type),

src/Microsoft.Azure.WebJobs.Extensions.OpenApi.Core/Visitors/RecursiveObjectTypeVisitor.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ public override bool IsVisitable(Type type)
4545
{
4646
isVisitable = false;
4747
}
48+
else if (type == typeof(TimeSpan))
49+
{
50+
isVisitable = false;
51+
}
4852
else if (type == typeof(DateTimeOffset))
4953
{
5054
isVisitable = false;
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Abstractions;
2+
using Microsoft.OpenApi.Models;
3+
using Newtonsoft.Json.Serialization;
4+
using System;
5+
using System.Collections.Generic;
6+
7+
namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Visitors
8+
{
9+
/// <summary>
10+
/// This represents the type visitor for <see cref="TimeSpan"/>.
11+
/// </summary>
12+
public class TimeSpanObjectTypeVisitor : TypeVisitor
13+
{
14+
/// <inheritdoc />
15+
public TimeSpanObjectTypeVisitor(VisitorCollection visitorCollection) : base(visitorCollection)
16+
{
17+
}
18+
19+
/// <inheritdoc />
20+
public override OpenApiSchema ParameterVisit(Type type, NamingStrategy namingStrategy)
21+
{
22+
return this.ParameterVisit(dataType: "string", dataFormat: "timespan");
23+
}
24+
25+
/// <inheritdoc />
26+
public override bool IsParameterVisitable(Type type)
27+
{
28+
var isVisitable = this.IsVisitable(type, TypeCode.Object) && type == typeof(TimeSpan);
29+
30+
return isVisitable;
31+
}
32+
33+
/// <inheritdoc />
34+
public override bool IsVisitable(Type type)
35+
{
36+
var isVisitable = this.IsVisitable(type, TypeCode.Object) && type == typeof(TimeSpan);
37+
38+
return isVisitable;
39+
}
40+
41+
/// <inheritdoc />
42+
public override void Visit(IAcceptor acceptor, KeyValuePair<string, Type> type, NamingStrategy namingStrategy, params Attribute[] attributes)
43+
{
44+
this.Visit(acceptor, name: type.Key, title: null, dataType: "string", dataFormat: "timespan", attributes: attributes);
45+
}
46+
47+
/// <inheritdoc />
48+
public override bool IsPayloadVisitable(Type type)
49+
{
50+
var isVisitable = this.IsVisitable(type);
51+
52+
return isVisitable;
53+
}
54+
55+
/// <inheritdoc />
56+
public override OpenApiSchema PayloadVisit(Type type, NamingStrategy namingStrategy)
57+
{
58+
return this.PayloadVisit(dataType: "string", dataFormat: "timespan");
59+
}
60+
}
61+
}

src/Microsoft.Azure.WebJobs.Extensions.OpenApi.Core/Visitors/TypeVisitor.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,11 @@ protected IOpenApiAny GetOpenApiPropertyDefault(OpenApiPropertyAttribute attr)
238238
return new OpenApiDateTime((DateTime) @default);
239239
}
240240

241+
if (@default is TimeSpan)
242+
{
243+
return new OpenApiString(@default.ToString());
244+
}
245+
241246
if (@default is DateTimeOffset)
242247
{
243248
return new OpenApiDateTime((DateTimeOffset) @default);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Abstractions;
3+
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Resolvers;
4+
using Newtonsoft.Json.Serialization;
5+
6+
namespace Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Tests.Fakes
7+
{
8+
public class FakeTimeSpanParameterExample : OpenApiExample<TimeSpan>
9+
{
10+
public override IOpenApiExample<TimeSpan> Build(NamingStrategy namingStrategy = null)
11+
{
12+
this.Examples.Add(OpenApiExampleResolver.Resolve("timeSpanValue1", new TimeSpan(6,12,14).ToString(), namingStrategy));
13+
this.Examples.Add(OpenApiExampleResolver.Resolve("timeSpanValue2", new TimeSpan(6,12,14,45).ToString(), namingStrategy));
14+
return this;
15+
}
16+
}
17+
}

test/Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Tests/Abstractions/OpenApiExampleTests.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,20 @@ public void Given_DateTimeOffsetType_When_Instantiated_Then_It_Should_Return_Res
179179
(result[exampleName].Value as OpenApiDateTime).Value.Should().Be(DateTimeOffset.Parse(exampleValue));
180180
}
181181

182+
[TestMethod]
183+
[DataRow("timeSpanValue1","06:12:14")]
184+
[DataRow("timeSpanValue2", "6.12:14:45")]
185+
public void Given_TimeSpanType_When_Instantiated_Then_It_Should_Return_Result(string exampleName, string exampleValue)
186+
{
187+
var namingStrategy = new DefaultNamingStrategy();
188+
var example = new FakeTimeSpanParameterExample();
189+
190+
var result = example.Build(namingStrategy).Examples;
191+
192+
result[exampleName].Value.Should().BeOfType<OpenApiString>();
193+
(result[exampleName].Value as OpenApiString).Value.Should().Be(exampleValue);
194+
}
195+
182196
[TestMethod]
183197
[DataRow("guidValue1", "74be27de-1e4e-49d9-b579-fe0b331d3642")]
184198
public void Given_GuidType_When_Instantiated_Then_It_Should_Return_Result(string exampleName, string exampleValue)

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public void Given_TypeCode_ToDataType_Should_Throw_Exception()
4343
[DataRow(typeof(DateTime), "string")]
4444
[DataRow(typeof(DateTimeOffset), "string")]
4545
[DataRow(typeof(Guid), "string")]
46+
[DataRow(typeof(TimeSpan), "string")]
4647
[DataRow(typeof(object), "object")]
4748
public void Given_TypeCode_ToDataType_Should_Return_Value(Type type, string expected)
4849
{
@@ -69,6 +70,7 @@ public void Given_TypeCode_ToDataFormat_Should_Throw_Exception()
6970
[DataRow(typeof(DateTime), "date-time")]
7071
[DataRow(typeof(DateTimeOffset), "date-time")]
7172
[DataRow(typeof(Guid), "uuid")]
73+
[DataRow(typeof(TimeSpan), "timespan")]
7274
[DataRow(typeof(object), null)]
7375
public void Given_TypeCode_ToDataFormat_Should_Return_Value(Type type, string expected)
7476
{

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ public void Given_NonGenericType_When_GetUnderlyingType_Invoked_Then_It_Should_R
107107
[DataRow(typeof(int?), typeof(int))]
108108
[DataRow(typeof(bool?), typeof(bool))]
109109
[DataRow(typeof(DateTime?), typeof(DateTime))]
110+
[DataRow(typeof(TimeSpan?), typeof(TimeSpan))]
110111
public void Given_NullableType_When_GetUnderlyingType_Invoked_Then_It_Should_Return_Result(Type type, Type expected)
111112
{
112113
var result = TypeExtensions.GetUnderlyingType(type);
@@ -129,6 +130,7 @@ public void Given_ListType_When_GetUnderlyingType_Invoked_Then_It_Should_Return_
129130
[DataRow(typeof(List<int?>), typeof(int))]
130131
[DataRow(typeof(List<bool?>), typeof(bool))]
131132
[DataRow(typeof(List<DateTime?>), typeof(DateTime))]
133+
[DataRow(typeof(List<TimeSpan?>), typeof(TimeSpan))]
132134
public void Given_NullableListType_When_GetUnderlyingType_Invoked_Then_It_Should_Return_Result(Type type, Type expected)
133135
{
134136
var result = TypeExtensions.GetUnderlyingType(type);
@@ -151,6 +153,7 @@ public void Given_DictionaryType_When_GetUnderlyingType_Invoked_Then_It_Should_R
151153
[DataRow(typeof(Dictionary<string, int?>), typeof(int))]
152154
[DataRow(typeof(Dictionary<string, bool?>), typeof(bool))]
153155
[DataRow(typeof(Dictionary<string, DateTime?>), typeof(DateTime))]
156+
[DataRow(typeof(Dictionary<string, TimeSpan?>), typeof(TimeSpan))]
154157
public void Given_NullableDictionaryType_When_GetUnderlyingType_Invoked_Then_It_Should_Return_Result(Type type, Type expected)
155158
{
156159
var result = TypeExtensions.GetUnderlyingType(type);

0 commit comments

Comments
 (0)