Closed NickDarvey closed 3 years ago
I don't think it's possible with the current options. But this would be a useful feature! It's implemented in WebSharper's JSON library and I've definitely made use of it in the past.
I think the implementing the writing might be something like:
/// Extensions (hopefully) coming with .NET 5
/// (https://github.com/dotnet/runtime/issues/31274)
/// from https://github.com/jet/FsCodec/blob/aab8dce0240469351172c43e962aaaa8b57f111f/src/FsCodec.SystemTextJson/JsonSerializerElementExtensions.fs#L21
[<AutoOpen>]
module private JsonSerializerExtensions =
open System.Runtime.InteropServices
type private JsonSerializer with
static member SerializeToElement(value: 'T, [<Optional; DefaultParameterValue(null)>] ?options: JsonSerializerOptions) =
JsonSerializer.Deserialize<JsonElement>(ReadOnlySpan.op_Implicit(JsonSerializer.SerializeToUtf8Bytes(value, defaultArg options null)))
let writeExpandedSingleField (writer: Utf8JsonWriter) (case: Case) (value: obj) (options: JsonSerializerOptions) =
writer.WriteStartObject()
writer.WriteString(fsOptions.UnionTagName, case.Name)
let element = JsonSerializer.SerializeToElement((case.Dector value).[0], options)
match element.ValueKind with
| JsonValueKind.Object ->
for property in element.EnumerateObject() do property.WriteTo(writer)
| _ ->
writer.WritePropertyName(case.Fields.[0].Name)
element.WriteTo(writer)
writer.WriteEndObject()
The trickiest part about implementing this enhancement for me is understanding how it should compose with the other options using the JsonUnionEncoding
flag enum. I guess I might be having trouble because not all options are expected to compose, like, not every combination is possible (e.g. JsonUnionEncoding.InternalTag
doesn't work with JsonUnionEncoding.UnwrapSingleFieldCases
, if I understand correctly).
I'm not quite familiar enough with this library to suggest a design here, so if you can recommend how to integrate this with the JsonUnionEncoding
options then I'm happy to try to implement it.
(Alternatively, and maybe a different piece of work, perhaps the options could be modelled as a bunch of DU types where only the valid combinations are representable. And/or the JsonUnionConverter
is split up so there's not quite so much conditional behaviour.)
I've started an implementation that reuses a chunk of the code for writing records, will create a draft PR soon.
The trickiest part about implementing this enhancement for me is understanding how it should compose with the other options using the
JsonUnionEncoding
flag enum.
As far as I can tell, it should be possible to use this option any time you have JsonUnionEncoding.NamedFields
enabled. But indeed we should be careful about the interaction with the various Unwrap
options.
I'm looking to 'unwrap' a record so that it's properties are at the same level as the case field.
Is there some kinda combination I could set for
myOptions
which would give me the behaviour I'm testing for here?