I'm trying to do a one way transform from F#'s discriminated union to strings upon serialization instead of the default `"Case": [value]". Being able to deserialize the value again is not an issue. Maybe possible with Json.NET?
// Fsharp 4.1.0
open Newtonsoft.Json // 10.0.3
type HowLame =
| PrettyLame
| SuperLame
type Lame = {
howLame: HowLame;
}
[<EntryPoint>]
let main argv =
let lame = { howLame = PrettyLame }
let ser = JsonConvert.SerializeObject(lame)
// {"soLame":{"Case":"PrettyLame"}} by default
printfn "%s" ser
// Desired
assert (ser = """{"soLame":"PrettyLame"}""")
0 // return an integer exit code
Creating a custom Json.NET JsonConverter and using it to decorate the discriminated union ("enum style") was enough to get this working the way I wanted. A good chunk of this is transliterated from @Brian Rogers answer in C# https://stackoverflow.com/a/22355712/1924257
open System
open Newtonsoft.Json // 10.0.3
open Newtonsoft.Json.Converters
type ToStringJsonConverter () =
inherit JsonConverter()
override this.CanConvert objectType = true;
override this.WriteJson (writer: JsonWriter, value: obj, serializer: JsonSerializer): unit =
writer.WriteValue(value.ToString())
override this.CanRead = false
override this.ReadJson (reader: JsonReader, objectType: Type, existingValue: obj, serializer: JsonSerializer) : obj =
raise (new NotImplementedException());
[<JsonConverter(typeof<ToStringJsonConverter>)>]
type HowLame =
| PrettyLame
| SuperLame
type Lame = {
howLame: HowLame
}
[<EntryPoint>]
let main argv =
let lame = { howLame = PrettyLame }
let ser = JsonConvert.SerializeObject(lame)
// {"howLame":"PrettyLame"}
printfn "%s" ser
0 // return an integer exit code
If you are willing to make the DU an enum (by specifying explicit values, which probably is OK since there is no 'payload'), you can use the standard StringEnumConverter
:
#r "../packages/Newtonsoft.Json/lib/net45/Newtonsoft.Json.dll"
open Newtonsoft.Json
type HowLame = PrettyLame=0 | SuperLame=1
type Lame = { howLame: HowLame; }
// in contrast to DUs, enums must be qualified, i.e. Enum.Value
let lame = { howLame = HowLame.PrettyLame }
let settings = JsonSerializerSettings()
settings.Converters.Add(Converters.StringEnumConverter())
let ser = JsonConvert.SerializeObject(lame, settings)
// val ser : string = "{"howLame":"PrettyLame"}"
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.