Search code examples
jsonf#type-providers

Is there a way to enumerate JSON properties using F# JsonProvider?


I parse some data in JSON format using F# and JSON Type Provider.

example.json:

{
    "contracts": {
        "11": {
            "id": 11,
            "date": "08.01.2021"
        },
        "12": {
            "id": 12,
            "date": "09.01.2021"
        },
        "13": {
            "id": 13,
            "date": "11.01.2021"
        }
    }
}

My F# code:

namespace Analyse
open Microsoft.FSharp.Reflection

module AnalyserExample =
open System
open FSharp.Data

let [<Literal>] SampleFile = @"example.json"
type ContractsProvider = JsonProvider<SampleFile>

let contracts () =
    let data = ContractsProvider.Parse("example.json")
    let contracts = data.Contracts
    contracts.``11``
    contracts.``12``
    contracts.``13``

JsonProvider works as expected, every contract is parsed as a field, but I want to enumerate them. I have some options. Using reflection to get a list of fields or transform JSON using some custom transformation before type provider initialization runs, but I like neither of them.

Is there a way to transform this structure into a sequence using JsonProvider, or some F# sorcery?


Solution

  • You can do this via the underlying JsonValue, which is what JsonProvider is built on:

    let data = ContractsProvider.Parse(sample)
    let contracts = data.Contracts
    for _, value in contracts.JsonValue.Properties() do
        printfn "%A" value
    

    There's little value in using JsonProvider at all in this scenario, though. You'd be better off skipping it, and running the parser dynamically instead:

    let data = JsonValue.Load("example.json")
    for _, value in data.["contracts"].Properties() do
        printfn "%A" value
    

    That way, you're not relying on the JSON to always consist exactly of contracts 11, 12 and 13.