3. 외부 REST API 서비스 호출하기 (이어서…)
POST 끝점에 DTO를 전달 할 수 있습니다.
전달 받을 record type을 선언합니다.
type UserRequestDto = {
Name : string
PhoneNumber : string
}
F#이 버전 업데이트 하면서 [<CLIMutable>] 어트리뷰트 없이도 역직렬화가 가능해졌습니다. 언제부터 가능했는지는 찾기 어렵군요. 정말 마음에 듭니다.
코드를 좀 더 고쳐 보겠습니다.
[<EntryPoint>]
let main _ =
let app = webApp {
...
post "/api/v2/users" (fun (httpContext: HttpContext) (req: UsersRequestDto) -> backgroundTask {
use httpClient = httpContext.RequestServices.GetRequiredKeyedService<HttpClient>("reqres")
let! response = httpClient.PostAsJsonAsync("/api/users", {|
Name = req.Name
PhoneNumber = req.PhoneNumber
|})
let! stream = response.Content.ReadAsStreamAsync()
return Results.Stream(stream, contentType= $"{response.Content.Headers.ContentType}")
})
}
다음 요청에 대해 정상적으로 응답을 받을 수 있습니다.
POST http://localhost:5013/api/v2/users
Content-Type: application/json
{
"name": "John Doe",
"phoneNumber": "821000000000"
}
---
application/json; charset=utf-8, 98 bytes
{
"name": "John Doe",
"phoneNumber": "821000000000",
"id": "334",
"createdAt": "2025-04-04T06:29:45.398Z"
}
도메인 기반 타입 선언을 DTO에 반영해 보겠습니다. UserRequestDto를 수정해 봅니다.
type Name = Name of string
type InternationalPhoneNumber = InternationalPhoneNumber of string
type UsersRequestDto = {
Name: Name
PhoneNumber : InternationalPhoneNumber
}
type Name = Name of string은 type Name = | Name of string을 줄여 쓴 표현이고 type Name = string과는 다릅니다.
하고자 하는 목적이 너무 달라요
C#의 using은 타입의 alias를 지원하지만 다른 타입을 만드는 거는 아니에요.
using CustomerId = int;
using OrderId = int;
CustomerId customerId = 1;
OrderId orderId = 2;
customerId = orderId; // 가능
OrderId 타입을 CustomerId 타입 변수에 넣고 싶지 않은데… C#은 언어에서 지원 하지 않지요.
F#은 언어에서 지원합니다 ㅋㅋ
type CustomerId = CustomerId of int
type OrderId = OrderId of int
let mutable customerId = CustomerId 1
let orderId = OrderId 1
customerId <- CustomerId 2
customerId <- orderId; // Error: This expression was expected to h…
수정한 코드는 F# 컴파일에 성공하지만 런타임에서 역직렬화에 실패합니다.
DU 에 대한 역질렬화는 F# CLR에 동작이 정의되어 있지 않습니다.
System.NotSupportedException: F# discriminated union serialization is not supported. Consider authoring a custom converter for the type.
열림 02:48PM - 15 Jul 21 UTC
api-needs-work
area-System.Text.Json
User Story
Priority:3
Cost:M
Team:Libraries
Concerning support for discriminated unions, it might be worth pointing out that… there is no one canonical way to encode DUs in JSON. DUs are used in many different ways in F# code, including the following:
- Single case DUs, e.g. `type Email = Email of string`, used to provide a type-safe wrapper for common values. A user might expect that `Email("email")` should serialize as its payload, `"email"`.
- Type-safe enums, e.g. `type Suit = Heart | Spade | Diamond | Club`. Users might reasonably expect that `Spade` should serialize as the union case identifier, `"Spade"`.
- Unions with arbitrary combinations of union cases and arities, e.g. `type Shape = Point | Circle of radius:float | Rectangle of width:float * length:float`. A value like `Circle(42.)` would require an encoding similar to `{ "shape" : "circle", "radius" : 42 }`. Users should be able to specify the case discriminator property name (`"shape"`) as well as the identifier for the union case (`Circle` mapping to `"circle"`).
In light of the above, I'm increasingly starting to think that System.Text.Json should not be providing a default mechanism for serializing DUs. Users would still be able to use [available custom converters](https://github.com/Tarmil/FSharp.SystemTextJson/) that provide the union encoding that suits their use case or perhaps use unions in their data contracts in a way that [bypasses the serialization layer altogether](https://eiriktsarpalis.wordpress.com/2018/10/30/a-contract-pattern-for-schemaless-datastores/).
_Originally posted by @eiriktsarpalis in https://github.com/dotnet/runtime/issues/29812#issuecomment-878303600_
If we do decide to support F# DUs in the future, it would likely be in the form of a publicly available converter factory à la [JsonStringEnumConverter](https://docs.microsoft.com/en-us/dotnet/api/system.text.json.serialization.jsonstringenumconverter?view=net-5.0) that configures one or more of the above alternative serialization formats.
DU에 대한 직렬화를 위해 별개의 라이브러리를 추가합니다.
System.Text.Json extensions for F# types
dotnet add package FSharp.SystemTextJson
(작성중…)
3개의 좋아요