[英]NSwag: How do you Use Custom Value Object Types in C# -> Swagger -> C# client?
我有一个 API 在输入和 output 中都使用Noda Time类型。 这些类型使用默认的 Noda Time 序列化格式(基本上是 ISO-8601 格式)序列化为 JSON 中的字符串。
我有一个 object 看起来像这样:
public class NodaTimeDataStructure
{
public System.DateTime DateTime { get; set; }
public DateInterval DateInterval { get; set; }
public DateTimeZone DateTimeZone { get; set; }
public Duration Duration { get; set; }
public Instant Instant { get; set; }
public Interval Interval { get; set; }
public IsoDayOfWeek IsoDayOfWeek { get; set; }
public LocalDate LocalDate { get; set; }
public LocalDateTime LocalDateTime { get; set; }
public LocalTime LocalTime { get; set; }
public Offset Offset { get; set; }
public OffsetDate OffsetDate { get; set; }
public OffsetDateTime OffsetDateTime { get; set; }
public OffsetTime OffsetTime { get; set; }
public Period Period { get; set; }
public ZonedDateTime ZonedDateTime { get; set; }
}
这通常会导致以下 Swagger JSON:
"NodaTimeDataStructure": {
"type": "object",
"additionalProperties": false,
"required": [
"dateTime", "duration", "instant", "interval", "isoDayOfWeek", "localDate", "localDateTime",
"localTime", "offset", "offsetDate", "offsetDateTime", "offsetTime", "zonedDateTime"
],
"properties": {
"dateTime": { "type": "string", "format": "date-time" },
"instant": { "type": "string", "format": "date-time" },
"zonedDateTime": { "type": "string", "format": "date-time" },
"offsetDateTime": { "type": "string", "format": "date-time" },
"localDateTime": { "type": "string", "format": "date-time" },
"localDate": { "type": "string", "format": "date" },
"localTime": { "type": "string", "format": "time" },
"duration": { "type": "string", "format": "time-span" },
"dateInterval": { "type": "array", "items": { "type": "string", "format": "date" } },
"dateTimeZone": { "$ref": "#/definitions/DateTimeZone" },
"interval": { "$ref": "#/definitions/Interval" },
"isoDayOfWeek": { "$ref": "#/definitions/IsoDayOfWeek" },
"offset": { "$ref": "#/definitions/Offset" },
"offsetDate": { "$ref": "#/definitions/OffsetDate" },
"offsetTime": { "$ref": "#/definitions/OffsetTime" },
"period": { "$ref": "#/definitions/Period" }
}
}
这使得无法在 C# 客户端中转换回正确的 Noda Time 类型。 除了具有完全相同格式( "date-time"
)的许多不同类型使得映射不可能之外,某些类型具有不幸的定义。 DateInterval
产生一个"date"
数组,因为它是LocalDate
的可枚举,但简单的开始/结束日期格式会更好。 其他方法是使用$ref
创建的,用于非常复杂的对象,其中包含绝对不感兴趣的字段。 请注意,所有这些都应该序列化为简单的字符串(可以说不是间隔)。
我可以创建自己的类型映射器并将它们添加到AspNetCoreToSwaggerGeneratorSettings
中,如下所示:
var nodaTimeTypeMappers = new[]
{
CreateTypeMapper(typeof(DateInterval), "date-interval"),
CreateTypeMapper(typeof(DateTimeZone), "date-time-zone"),
CreateTypeMapper(typeof(Duration), "duration"),
CreateTypeMapper(typeof(Instant), "instant"),
CreateTypeMapper(typeof(Interval), "interval"),
CreateTypeMapper(typeof(IsoDayOfWeek), "iso-day-of-week"),
CreateTypeMapper(typeof(LocalDate), "local-date"),
CreateTypeMapper(typeof(LocalDateTime), "local-date-time"),
CreateTypeMapper(typeof(LocalTime), "local-time"),
CreateTypeMapper(typeof(Offset), "offset"),
CreateTypeMapper(typeof(OffsetDate), "offset-date"),
CreateTypeMapper(typeof(OffsetDateTime), "offset-date-time"),
CreateTypeMapper(typeof(OffsetTime), "offset-time"),
CreateTypeMapper(typeof(Period), "period"),
CreateTypeMapper(typeof(ZonedDateTime), "zoned-date-time"),
};
foreach (var typeMapper in nodaTimeTypeMappers)
{
settings.TypeMappers.Add(typeMapper);
}
PrimitiveTypeMapper CreateTypeMapper(Type type, string name)
{
return new PrimitiveTypeMapper(type, s =>
{
s.Type = JsonObjectType.String;
s.Format = "noda-time-" + name;
});
}
得到这样的东西:
"NodaTimeRequest": {
"type": "object",
"additionalProperties": false,
"required": [
"dateTime", "duration", "instant", "interval", "isoDayOfWeek", "localDate", "localDateTime",
"localTime", "offset", "offsetDate", "offsetDateTime", "offsetTime", "zonedDateTime"
],
"properties": {
"dateTime": { "type": "string", "format": "date-time" },
"dateInterval": { "type": "string", "format": "noda-time-date-interval" },
"dateTimeZone": { "type": "string", "format": "noda-time-date-time-zone" },
"duration": { "type": "string", "format": "noda-time-duration" },
"instant": { "type": "string", "format": "noda-time-instant" },
"interval": { "type": "string", "format": "noda-time-interval" },
"isoDayOfWeek": { "type": "string", "format": "noda-time-iso-day-of-week" },
"localDate": { "type": "string", "format": "noda-time-local-date" },
"localDateTime": { "type": "string", "format": "noda-time-local-date-time" },
"localTime": { "type": "string", "format": "noda-time-local-time" },
"offset": { "type": "string", "format": "noda-time-offset" },
"offsetDate": { "type": "string", "format": "noda-time-offset-date" },
"offsetDateTime": { "type": "string", "format": "noda-time-offset-date-time" },
"offsetTime": { "type": "string", "format": "noda-time-offset-time" },
"period": { "type": "string", "format": "noda-time-period" },
"zonedDateTime": { "type": "string", "format": "noda-time-zoned-date-time" }
}
}
这允许格式像现有格式一样使用( "date-time"
、 "date"
、 "time"
、 "time-span"
),但看在上帝的份上,我无法弄清楚如何制作swagger2csclient
使用这些格式正确转换回相应的 Noda Time 类型。 我通常会遗漏一些东西还是目前不可能?
我没有 Swagger json 问题的解决方案,但我可以帮助解决 C# 客户端生成部分。
我们不会从 NSwag json生成客户端,而是让 NSwagStudio 使用反射生成客户端。 我正在使用“通过反射的 Web API”,运行时设置为“默认”:
This generator "uses .NET reflection to analyze ASP.NET Web API or ASP.NET Core controllers". 当然,您的里程可能会有所不同 - 还有一个“.NET 程序集”选项和/或您可能需要明确设置运行时。
在右侧窗格中,单击“CSharp Client”并切换到“CSharp Client”选项卡:
在上面的屏幕截图中可以看到第一份秘制酱汁:我们将NodaTime
添加为一个额外的命名空间。
再往下,我们需要让 NSwagStudio 生成 DTO 类,并且——这是真正重要的事情——不要通过将 NodaTime 类型添加到“排除的类型名称”列表中来生成它们:
我使用的类型排除字符串是: DateInterval,DateTimeZone,Duration,Instant,Interval,IsoDayOfWeek,LocalDate,LocalDateTime,LocalTime,Offset,OffsetDate,OffsetDateTime,OffsetTime,Period,ZonedDateTime,CalendarSystem,Era
。
您还想查看许多其他选项。 完成后,按Generate Outputs
并生成 C# 客户端。
将客户端粘贴到引用 NodaTime 的项目中,我们可以看到使用了 NodaTime 类型:
我的测试使用了你的 class NodaTimeDataStructure
和这个 controller:
[Route("api/[controller]")]
[ApiController]
public class NodaTimeController
{
[HttpGet]
public NodaTimeDataStructure Get() => new NodaTimeDataStructure();
}
出于此测试/演示的目的,我将其构建到一个库中,该库针对 .NET 4.8 并使用 ASP.NET Core 2.2。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.