Skip to content
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

How to serialize a list to a Json object #77

Open
felixbecker opened this issue Sep 16, 2016 · 4 comments
Open

How to serialize a list to a Json object #77

felixbecker opened this issue Sep 16, 2016 · 4 comments

Comments

@felixbecker
Copy link

Hi,

I have a question regarding a list serialization. Since I could not find any pointers in the tests or docs. I would be great if someone could point me in the right direction.

Given I have a type like this:

type Post = {
    Id: Guid
    Title: string
    Body: string
} with static member ToJson(x:Post) = json{
        do! Json.write "id" x.Id
        do! Json.write "title" x.Title
        do! Json.write "body" x.Body
}

and a list of posts like this

 let post1 = {Id= Guid.NewGuid();Title="Title hello world post 1";Body="My body"}
 let post2 = {Id= Guid.NewGuid();Title="Title hello world post 2";Body="My body"}
 let listOfPosts = [post1;post2]

    listOfPosts
        |> Json.serialize
        |> Json.formatWith JsonFormattingOptions.Pretty

this would results obviously in this

"[
  {
    "body": "My body",
    "id": "0356c901-e1fa-4bae-8fe3-70061d2e05f3",
    "title": "Title hello world post 1"
  },
  {
    "body": "My body",
    "id": "292a275b-960e-46b4-b04b-c3e214c78b0d",
    "title": "Title hello world post 2"
  }
]" 

But how can I write a custom list serialization function that would produce something like this to an object graph:

"{
  "0356c901-e1fa-4bae-8fe3-70061d2e05f3":{
    "body": "My body",
    "title": "Title hello world post 1"
  },
  "292a275b-960e-46b4-b04b-c3e214c78b0d":{
    "body": "My body",
    "title": "Title hello world post 2"
  }
}"

Thanks for any help.

@kolektiv
Copy link
Member

Oh that's interesting! Sorry i've not got back to you sooner, I was away for the weekend, but that's an interesting question. I'll have to play around with it and have a think about that - but I'll try and get back to you soon 😄

@ingted
Copy link

ingted commented Oct 23, 2016

Hi kolektiv & felixbecker,

May I ask you here? Because I think I am doing something like this issue (not very sure), and my (useless / full of bug) method is

e.g.

At first I have a Monkey type, and I hope I could ## serialize IDictionary``2[int64, Monkey]

Yeah, I guess this is easy to transform to a ## list ^_^

#r @"..\..\..\chiron\src\Chiron\bin\Chiron.dll"
#r @"..\..\..\aether\src\Aether\bin\Aether.dll"
#r @"..\..\..\..\gdrive_anighost\fparsec\Build\VS14-PCL\bin\Debug\FParsec.dll"
#r @"..\..\..\..\gdrive_anighost\fparsec\Build\VS14-PCL\bin\Debug\FParsecCS.dll"

open Aether
open Aether.Operators
open Chiron
open Chiron.Operators
open System.Collections.Concurrent
open System.Collections.Generic
open System.Runtime.CompilerServices

[<CLIMutable>]
type Monkey =
  { sound : string
    height : decimal }

  static member ToJson (x : Monkey) =
    Json.write "sound" x.sound
    *> Json.write "height" x.height

So I define a extension method like this:

[<Extension>]
type ExtensionMethds2 () = 
    [<Extension>]
    static member inline ToJson (dic: IDictionary<int64, Monkey>): Json<unit> =
        Seq.fold (fun (sn : Json<unit>) key ->
            let x = dic.[key]
            sn 
            *> Json.write (key.ToString()) x
            ) (Json.init ()) dic.Keys

But when I tried to serialize it with:

let dictest = dict [123L, { sound = "ooh"; height = 1.53m }; 456L, { sound = "ooh"; height = 1.53m }]
Json.format (Json.serialize dictest)

Fsi.exe complains:

StatExtract.fsx(744,29): error FS0001: No overloads match for method 'ToJson'. The available overloads are shown below (or in the Error List window).
Possible overload: 'static member ToJsonDefaults.ToJson : x:unit -> Json<unit>'. Type constraint mismatch. The type 
    IDictionary<int64,Monkey>    
is not compatible with type
    unit    
The type 'IDictionary<int64,Monkey>' is not compatible with the type 'unit'.
Possible overload: 'static member ToJsonDefaults.ToJson : x:bool -> Json<unit>'. Type constraint mismatch. The type 
    IDictionary<int64,Monkey>    
is not compatible with type
    bool    

Even I add this code, it still not work...

type ToJsonDefaults with 
    static member inline ToJson (x: IDictionary<int64, Monkey>) =
        x.ToJson()

And I take a look at the source code:

    let inline internal toJsonDefaults (a: ^a, _: ^b) =
        ((^a or ^b) : (static member ToJson: ^a -> unit Json) a)

But I couldn't understand this syntax... would you please give me some clue / url / doc for understand this syntax? (esp. ((^a or ^b) : (static member ToJson: ^a -> unit Json) a))

Thank you so much!!

@ingted
Copy link

ingted commented Oct 23, 2016

Hi,

I got some workaround:

type Dicttc = Dicttc of IDictionary<int64, Monkey>

[<Extension>]
type ExtensionMethds2 () = 
    [<Extension>]
    static member inline ToJson2 (dic: Dicttc): Json<unit> =
        let ddic = (fun (Dicttc d) -> d) dic 
        Seq.fold (fun (sn : Json<unit>) key ->
            let x = ddic.[key]
            sn 
            *> Json.write (key.ToString()) x
            ) (Json.init ()) ddic.Keys

type Dicttc with
    static member ToJson (x : Dicttc) =
        x.ToJson2()

let dictest = Dicttc (dict [123L, { sound = "ooh"; height = 1.53m }; 456L, { sound = "ooh"; height = 1.53m }])
Json.format (Json.serialize dictest)

The result is:

val it : string =
  "{"123":{"height":1.53,"sound":"ooh"},"456":{"height":1.53,"sound":"ooh"}}"

@ingted
Copy link

ingted commented Oct 23, 2016

Hi again,

A refinement... no extension method required! (in the fact, extension method way caused another issues.)

type Ooo = Ooo of IDictionary<int64, Monkey[]> with
    static member ToJson (x: Ooo) =
        let xx = (fun (Ooo d) -> d) x 
        Seq.fold (fun (sn : Json<unit>) key ->
            let xxx = xx.[key]
            sn 
            *> Json.write (key.ToString()) xxx
            ) (Json.init ()) xx.Keys

let dictest2 = Ooo   (dict [123L, [|{ sound = "ooh"; height = 0.53m }|]; 456L, [|{ sound = "ooh2"; height = 1.53m }|]])

Json.format (Json.serialize dictest2)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants