'How to convert a Google Repeated Field to a standard F# list or array (FSharp.GrpcCodeGenerator)?
I've been experimenting with the NuGet package FSharp.GrpcCodeGenerator in converting my proto files to F# types.
On my client side (in F#), I have:
namespace StargateIX.Network
open System
open Grpc.Core
open Protocol.ProtoBuf
open Grpc.Net.Client
module ClientNetwork =
let channel = GrpcChannel.ForAddress("https://localhost:5001/")
let client = PatientService.PatientServiceClient(channel)
let req = GetAllPatientsRequest.empty()
let resp = client.GetAllPatients(req).Patients
?????????????
printfn "%s" resp.Message
Where GetAllPatientsRequest is an empty message, i.e.
message GetAllPatientsRequest {}
and the reponse to GetAllPatients is
message PatientListResponse {
repeated Patient Patients = 1;
}
How do I convert the PatientListResponse with its repeated field to a standard F# Array or list such that I can print it?
(Also, all this should be done asynchronously).
message Patient {
int32 PatientId =1;
google.protobuf.Timestamp BirthDate = 2;
string FirstName =3;
string LastName=4;
google.protobuf.StringValue Mi=5;
int32 ChartNumber=6;
}
TIA
Solution 1:[1]
This works -- or at least it compiles. I don't really like it since the fields for lastname, firstname, and birthdate will NEVER be null. So this seems unnecessarily complicated.
type Patient =
{
PatientId : int option
BirthDate : DateTime
FirstName : string
LastName : string
Mi : string
ChartNumber : int
}
module ClientNetwork =
let patientToDomain (x:Protocol.ProtoBuf.Patient) : Patient = {PatientId = match x.PatientId with
| ValueNone -> None
| ValueSome d -> Some d;
BirthDate = match x.BirthDate with
| ValueNone -> DateTime(01,01,01)
| ValueSome d -> d.ToDateTime().Value ;
FirstName = match x.FirstName with
| ValueNone -> ""
| ValueSome s -> s;
LastName = match x.LastName with
| ValueNone -> ""
| ValueSome s -> s;
Mi = match x.Mi with
| ValueNone -> ""
| ValueSome s -> s.ToString();
ChartNumber = match x.ChartNumber with
| ValueNone -> 0
| ValueSome i -> i}
let channel = GrpcChannel.ForAddress("https://localhost:5001/")
let client = PatientService.PatientServiceClient(channel)
let req = GetAllPatientsRequest.empty()
let resp = client.GetAllPatients(req).Patients |> Seq.map patientToDomain
resp |> printfn "%A"
This seems a little bit better but drops the error checks.
let patientToDomain (x:Protocol.ProtoBuf.Patient) : Patient =
{ PatientId = match x.PatientId with
| ValueNone -> None
| ValueSome d -> Some d;
BirthDate = x.BirthDate.Value.ToDateTime().Value;
FirstName = x.FirstName.Value;
LastName = x.LastName.Value;
Mi = match x.Mi with
| ValueNone -> ""
| ValueSome s -> s.ToString();
ChartNumber = x.ChartNumber.Value }
Now adding the async part gives:
module ClientNetwork =
let channel = GrpcChannel.ForAddress("https://localhost:5001/")
let client = PatientService.PatientServiceClient(channel)
let patientToDomain (x:Protocol.ProtoBuf.Patient) : Patient =
{ PatientId = match x.PatientId with
| ValueNone -> None
| ValueSome d -> Some d;
BirthDate = x.BirthDate.Value.ToDateTime().Value;
FirstName = x.FirstName.Value;
LastName = x.LastName.Value;
Mi = match x.Mi with
| ValueNone -> ""
| ValueSome s -> s.ToString();
ChartNumber = x.ChartNumber.Value }
let req = GetAllPatientsRequest.empty()
let GetAllPatientsAsync req =
async {
let! resp = client.GetAllPatientsAsync(req).ResponseAsync |> Async.AwaitTask
return resp.Patients |> Seq.map patientToDomain
}
This compiles correctly so I will go with it. Better answers are more then welcome!
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
