-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Null value option roundtrip #8
Comments
One solution would be changing the However this would probably be annoying for other consumers. |
Example: open FsCheck.Xunit
open Fleece
open Fleece.Operators
open FSharpx.Choice
open Xunit
open Swensen.Unquote
type Foo = { maybeStr : string option }
with
static member Create a = {maybeStr = a}
static member ToJSON (x : Foo) =
jobj [ "maybeStr" .= x.maybeStr ]
static member FromJSON (_ : Foo) =
function
| JObject o -> Foo.Create <!> o.@?"maybeStr"
| x -> sprintf "Foo %A" x |> Choice2Of2
[<Fact>]
let ``none to json`` () =
let foo = {maybeStr = None}
let x = toJSON foo |> string
test <@ x = """{"maybeStr":null}""" @>
(* PASSED *)
[<Fact>]
let ``null in json to none`` () =
let src = """{"maybeStr":null}"""
let x = System.Json.JsonValue.Parse(src);
let foo : Choice<Foo,string> = fromJSON x
test <@ foo = Choice1Of2 { maybeStr = None } @>
(* FAILED
Choice1Of2 {maybeStr = Some null;} = Choice1Of2(NewRecord (Foo, NewUnionCase (None)))
Choice1Of2 {maybeStr = Some null;} = Choice1Of2({maybeStr = null;})
false
*) See also: https://gist.github.com/dtchepak/cf498a1f44b59a6a4dce |
Actually there's no need to wrap the |
Not sure if it makes a difference, but our actual case is more like this: type Bar = A | B
with
static member ToJSON (x : Bar) =
match x with | A -> JString "A" | B -> JString "B"
static member FromJSON (_ : Bar) =
function
| JString "A" -> Choice1Of2 A
| JString "B" -> Choice1Of2 B
| _ -> Choice2Of2 "could not parse Bar"
type Foo = { bar : Bar option }
with
static member Create a = {bar = a}
static member ToJSON (x : Foo) =
jobj [ "bar" .= x.bar ]
static member FromJSON (_ : Foo) =
function
| JObject o -> Foo.Create <!> o.@?"bar"
| x -> sprintf "Foo %A" x |> Choice2Of2 |
The last case you mention is slightly different: when using It can't roundtrip like that because of its semantics. If you change that to |
BTW you might want to use |
I've been working with Dave, we figured out a possible solution. We created these functions:
Then we create objects with optional elements like this:
Dave wondered if the jobj function could be modified to filter out pairs with null keys? |
Yes, I think that makes sense. It's either that or throwing an exception. Implemented that change in b8964b0 . As for optional serialization elements, personally I'd rather be explicit about it, even if it's a bit more verbose, e.g.: static member ToJSON (x : AClass) =
jobj [
yield "MandatoryValue" .= x.mandatoryValue
if x.optionalValue <> null then
yield "OptionalValue" .= x.optionalValue
] Also, none of this seems to be related to the original description of this issue... |
@mausch I think the decision of not encoding the "Someness" of an option cause not only this issue with reference types but with any other option-like nesting, including nesting with option itself:
gives and |
Recently was bitten by this issue, luckily was caught in testing. Fundamental issue is that there are more values for a type like Would it be possible to special case the encoder/decoder for a Some outer option to include the case in the encoded form? Going fully verbose with option case names in all cases is probably a pain for many other consumers of the data, but if you choose to use complex nested optional types then you can deal with the verbosity? |
Roundtripping a
string option
doesn't work. Problem is, serializingSome null
outputsnull
which then gets deserialized asNone
. This problem can be generalized to all reference types within an option.This doesn't happen in Haskell/Aeson because strings are not nullable.
The text was updated successfully, but these errors were encountered: