[Question] Is it possible to use already encoded objects to encode a container value
lontivero opened this issue · 2 comments
Note: if this is not the correct place for this please let me know where I can get help. Thanks.
I need to serialize an array and the expected result is this:
["EVENT", "subcription-12345", {"property": "value"}]
The third element is already serialized, what means that I already have the string "{"property": "value"}" that I get from a database. All this means that I could create this by simply concatenating strings but it feels wrong.
If I do this the result is :
["EVENT", "subcription-12345", "{\"property\": \"value\"}"]
type SubscriptionId = string
type SerializedEvent = string
type RelayMessage =
| RMEvent of SubscriptionId * SerializedEvent
let encode = function
| RMEvent (subscriptionId, serializedEvent) ->
Encode.tuple3
Encode.string
Encode.string
Encode.string
("EVENT", subscriptionId, serializedEvent)
let serializedMessage =
RMEvent ("subscription-1234", """{"property":"value"}""")
|> encode
|> Encode.toString 0
Is there any way to do what I need?
Hello,
From a JSON point of view, if you have a serialised value and you try to embed it into a JSON it is the same as if you have a string.
Indeed, the serialised value is just a string and is handle as it.
In JavaScript code, what you do is equivalent to:
var embedJson = '{"property":"value"}';
JSON.stringify({ event: embedJson})
// '{"event":"{\\"property\\":\\"value\\"}"}'
If you want to avoid the double serialisation, you need to deserialise the embedJson so it can be serialise only once.
var embedJson = '{"property":"value"}';
var deserialisedJson = JSON.parse(embedJson);
JSON.stringify({ event: deserialisedJson})
// '{"event":{"property":"value"}}'
You can do that in Thoth.Json by adding a custom Encode
function:
module Encode =
let passthrough value =
JS.JSON.parse value
let encode = function
| RMEvent (subscriptionId, serializedEvent) ->
Encode.tuple3
Encode.string
Encode.string
Encode.passthrough
("EVENT", subscriptionId, serializedEvent)
However, if you do such a thing it means that the JSON you get as an output is not respecting the Domain you have in F#.
Your domain say:
type SubscriptionId = string
type SerializedEvent = string
type RelayMessage =
| RMEvent of SubscriptionId * SerializedEvent
but your JSON output map to:
type SubscriptionId = string
type SerializedEvent = {| property: string |} //Using anonymous record for simplicity
type RelayMessage =
| RMEvent of SubscriptionId * SerializedEvent
Personally, I would not use the passthrough
encoder that I showed you because it doesn't feel like a robust solution to me. And just postponing the problem.
Depending on your use case, I would probably keep the serialised event as it is and decode it later when needed. Or if having a clean JSON is important, then I would probably rework the domain to use something like:
type SubscriptionId = string
type SerializedEvent =
| Event1 of ...
| Event2 of ...
| Event3 of ...
type RelayMessage =
| RMEvent of SubscriptionId * SerializedEvent
in order to have full control over the JSON and have the domain and JSON representation aligned.
I appreciate very much the quality of your response. If well the project I am working on is simply a toy to learn F#, I am playing with some optimizations (early ones) that no other projects seem to have consider, like avoiding the re-serialization of events (json messages). In this case I would go with the simplest solution that is concatenate strings on the relay side.
All the rest will use Thoth.Json. I love this project, really.