Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

f# - how to serialize option and DU as value or null (preferably with json.net)

How can i get my json from web api to format only value or null for Option types and Discriminated Unions preferably using Newtonsoft.

I am currently using Newtonsoft and only have to add this to web api for it to work:

config.Formatters.JsonFormatter.SerializerSettings <- new JsonSerializerSettings()

When i consume the data on my side, i can easily convert it back to an F# item using: JsonConvert.DeserializeObject<'a>(json)

The api will be consumed by NON .NET clients as well so i would like a more standard formatted json result.

I would like to to fix my issue, w/o having to add code or decorators to all of my records/DU in order for it to work. I have lots of records with lots of properties, some are Option.

ex (this is how DU is serializing):

// When value
"animal": {
  "case": "Dog"
}

// When no value
"animal": null

This is what I need:

// When value 
"animal": "Dog"

// When no value 
"animal": null

This is how an Option type is serializing:

"DocumentInfo": {
  "case": "Some",
  "fields": [
    {
      "docId": "77fb9dd0-bfbe-42e0-9d29-d5b1f5f0a9f7",
      "docType": "Monkey Business",
      "docName": "mb.doc",
      "docContent": "why cant it just give me the values?"
    }
  ]
}

This is what I need:

"DocumentInfo": {
   "docId": "77fb9dd0-bfbe-42e0-9d29-d5b1f5f0a9f7",
   "docType": "Monkey Business",
   "docName": "mb.doc",
   "docContent": "why cant it just give me the values?"
}

Thank you :-)

like image 376
schmoopy Avatar asked Sep 13 '25 01:09

schmoopy


1 Answers

You could try using Chiron. I haven't used it myself so I can't give you an extensive example, but https://neoeinstein.github.io/blog/2015/12-13-chiron-json-ducks-monads/index.html has some bits of sample code. (And see https://neoeinstein.github.io/blog/2016/04-02-chiron-computation-expressions/index.html as well for some nicer syntax). Basically, Chiron knows how to serialize and deserialize the basic F# types (strings, numbers, options, etc.) already, and you can teach it to serialize any other type by providing that type with two static methods, ToJson and FromJson:

static member ToJson (x:DocumentInfo) = json {
    do! Json.write "docId" x.docId
    do! Json.write "docType" x.docType
    do! Json.write "docName" x.docName
    do! Json.write "docContent" x.docContent
}
static member FromJson (_:DocumentInfo) = json {
    let! i = Json.read "docId"
    let! t = Json.read "docType"
    let! n = Json.read "docName"
    let! c = Json.read "docContent"
    return { docId = i; docType = t; docName = n; docContent = c }
}

By providing those two static methods on your DocumentInfo type, Chiron will automatically know how to serialize a DocumentInfo option. At least, that's my understanding -- but the Chiron documentation is sadly lacking (by which I mean literally lacking: it hasn't been written yet), so I haven't really used it myself. So this may or may not be the answer you need, but hopefully it'll be of some help to you even if you don't end up using it.

like image 137
rmunn Avatar answered Sep 16 '25 08:09

rmunn