Reputation: 3224
I'm writing an F# library to call an HTTP REST API. The JSON body for the HTTP request is different based on how much or what type of information the request should send back.
For example, below is code to create a json body, using anonymous records, for an HTTP request to list out files in a project, https://documentation.dnanexus.com/developer/api/search#api-method-system-finddataobjects.
type Request = {
ApiToken: ApiToken
ProjectId: ProjectId
StartingAt: ObjectId option
}
module Request =
let toJson request =
let (ProjectId projectId) = request.ProjectId
let baseJson = {| scope = {| project = projectId
recurse = true |}
describe = true |}
match request.StartingAt with
| Some (ObjectId objectId) ->
{| baseJson with starting = {| project = projectId
id = objectId |} |}
| None ->
baseJson
This code does not compile. Instead, in the last line of this example, the compiler throws the following error:
This anonymous record does not have enough fields. Add the missing fields [starting].F# Compiler(1)
Is it possible to write a function that returns anonymous records with different structures?
Upvotes: 1
Views: 201
Reputation: 3502
This isn't a problem with anonymous records per se - it's that there's no clear return type of toJson
- depending on the branch, you return a different type.
You have a few options:
starting
an object, which can be set to null on the None branch: match request.StartingAt with
| Some (ObjectId objectId) ->
{| baseJson with starting = box {| project = projectId
id = objectId |} |}
| None ->
{| baseJson with starting = null |}
match request.StartingAt with
| Some (ObjectId objectId) ->
serialize
{| baseJson with starting = {| project = projectId
id = objectId |} |}
| None ->
serialize baseJson
where serialize is a function that takes any 'T and returns a string.
The main thing is that both "branches" of the match expression have to return the same type. This is the same for any branching expression in F# e.g. match or if / else. And it applies for all types - primitives, records, tuples, unions etc.
Upvotes: 3