我在用着Optional<T>
在我的 DTO 中实现 Json Patch (details https://stackoverflow.com/questions/71024060/distinguish-between-null-and-not-present-using-json-merge-patch-with-netcore-web/71074603#71074603)。类型 T 存储在Optional<T>
班级。 Optional 类允许区分 null 和未提供。
public readonly struct Optional<T>
{
public Optional(T? value)
{
this.HasValue = true;
this.Value = value;
}
public bool HasValue { get; }
public T? Value { get; }
public static implicit operator Optional<T>(T value) => new Optional<T>(value);
public override string ToString() => this.HasValue ? (this.Value?.ToString() ?? "null") : "unspecified";
}
我使用的第一个 DTO 仅包含原始类型,例如
public class PatchGroupDTO
{
public Optional<Guid?> SalesGroupId { get; init; }
public Optional<string?> Name { get; init; }
}
Swagger UI 显示的示例是错误的,因为它显示属性“value”:
{
"salesGroupId": {
"value": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
},
"name": {
"value": "string"
}
}
我们的解决方案是映射 Startup.cs 中的类型。
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "xxx.API", Version = "v1" });
c.MapType<Optional<Guid?>>(() => new OpenApiSchema { Type = "string", Format = "uuid" });
c.MapType<Optional<string?>>(() => new OpenApiSchema { Type = "string" });
c.MapType<Optional<bool?>>(() => new OpenApiSchema { Type = "boolean" });
c.MapType<Optional<int?>>(() => new OpenApiSchema { Type = "integer" });
})
该示例随后正确显示为:
{
"salesGroupId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name":"string"
}
在我最新的 DTO 中,我需要嵌套对象。简化的 DTO 如下所示:
public record UpdateCartDTO
{
public Optional<AddressDTO?> InvoicingAddress { get; init; }
public Optional<List<CommentDTO>?> Comments { get; init; }
public Optional<List<string>?> ReservationCodes { get; init; }
};
该示例将再次错误地显示嵌套值属性:
{
"invoicingAddress": {
"value": {
"type": "string",
"receipient": "string",
"deliveryInstructio": "string",
"street": "string",
"streetNumber": "string",
"streetAffix": "string",
"zip": "string",
"city": "string",
"state": "string",
"isO3": "string"
}
},
"comments": {
"value": [
{
"language": "string",
"comment": "string"
}
]
},
"reservationCodes": {
"value": [
"string"
]
}
}
List<string>
可以映射为:
c.MapType<Optional<List<string>?>>(
() => new OpenApiSchema { Type = "array", Items = new OpenApiSchema { Type="string" } });
我在映射嵌套对象时遇到问题。我试过:
c.MapType<Optional<AddressDTO?>>(() => new OpenApiSchema { Type = "object" });
但这只显示空括号{}
。按照我理解 api 的方式,我需要手动定义 AddressDTO 的所有类型Item = new OpenApiSchema{...}
. 有没有什么解决方案可以只引用AddressDTO?
为Optional中使用的每个T定义一个MapType通常很麻烦。有什么办法可以实现从Optional到T的通用映射吗?就像是:
c.MapType<Optional<T?>>(() => new OpenApiSchema { Object= "T"});