I'm working on a discord API wrapper and having some grief with trying to define types for gateway event data. Some are very simple, but some like MESSAGE_CREATE are pretty painful in the way I've been doing them:
[<JsonConverter(typeof<MessageCreateReceiveEventExtraFieldsMentionConverter>)>]
type MessageCreateReceiveEventExtraFieldsMention = {
User: User
ExtraFields: MessageCreateReceiveEventExtraFieldsMentionExtraFields
}
and MessageCreateReceiveEventExtraFieldsMentionExtraFields = {
[<JsonPropertyName "member">] Member: GuildMember option // TODO: Partial
}
and MessageCreateReceiveEventExtraFieldsMentionConverter () =
inherit JsonConverter<MessageCreateReceiveEventExtraFieldsMention> ()
override _.Read (reader, typeToConvert, options) =
let success, document = JsonDocument.TryParseValue &reader
if not success then raise (JsonException())
let json = document.RootElement.GetRawText()
{
User = Json.deserializeF json;
ExtraFields = Json.deserializeF json;
}
override _.Write (writer, value, options) =
let user = Json.serializeF value.User
let extraFields = Json.serializeF value.ExtraFields
writer.WriteRawValue (Json.merge user extraFields)
// https://discord.com/developers/docs/events/gateway-events#message-create
[<JsonConverter(typeof<MessageCreateReceiveEventConverter>)>]
type MessageCreateReceiveEvent = {
Message: Message
ExtraFields: MessageCreateReceiveEventExtraFields
}
and MessageCreateReceiveEventExtraFields = {
[<JsonPropertyName "guild_id">] GuildId: string option
[<JsonPropertyName "member">] Member: GuildMember option // TODO: Partial
[<JsonPropertyName "mentions">] Mentions: MessageCreateReceiveEventExtraFieldsMention list
}
and MessageCreateReceiveEventConverter () =
inherit JsonConverter<MessageCreateReceiveEvent> ()
override _.Read (reader, typeToConvert, options) =
let success, document = JsonDocument.TryParseValue &reader
if not success then raise (JsonException())
let json = document.RootElement.GetRawText()
{
Message = Json.deserializeF json;
ExtraFields = Json.deserializeF json;
}
override _.Write (writer, value, options) =
let message = Json.serializeF value.Message
let extraFields = Json.serializeF value.ExtraFields
writer.WriteRawValue (Json.merge message extraFields)
Because you cant extend a record, I'm needing to make these ExtraFields types and then serialize the properties. This one is particularly bad because I have two layers of that needing to be done. In use, this also isn't pleasant as it ends up as data.ExtraFields.Mentions[0].ExtraFields.Member. On top of this, I need to create partial types, which are basically the same as the normal records but where everything are options.
Is there a cleaner way I could be doing this? This is with FSharp.SystemTextJson