Search code examples
f#type-providers

F# - JSON Type Provider - Literal String


I have an interesting problem using the F# Type Provider. Using the following sample json to generate the required type works beautifully but with one glaring issue - one of the values is a literal string ("235") but that string does not occur in the real data - each new record has a different three-digit number:

{
"record": {
    "235": {
        "Id": "001",
        "Name": "A. N. Other",
        "IdDatetime": "2017-11-11T13:10:00+00:00"
        ...
    }
    "255": {
        "Id": "005",
        "Name": "D. Other",
        "IdDatetime": "2017-11-11T13:10:00+00:00"
        ...
    }
}

So, unfortunately, I cannot access the Id, Name, and IdDateTime fields without knowing the three-digit code in advance!

Any advice?


Solution

  • Do you have to use the JsonProvider? There is a simpler JsonParser in FSharp.Data that allows easier access to more dynamic data. After that it's just a simple exercise to destructure it to get to the inner part.

    #r @"../packages/FSharp.Data/lib/net40/FSharp.Data.dll"
    
    open FSharp.Data
    open FSharp.Data.JsonExtensions
    
    [<Literal>]
    let jsonText = """
    {
    "record": {
        "235": {
            "Id": "001",
            "Name": "A. N. Other",
            "IdDatetime": "2017-11-11T13:10:00+00:00"
            }
        }
    }
    """
    
    let json1 = JsonValue.Parse(jsonText)
    let json2 = json1?record
    
    let json3 = 
        match json2 with
            | JsonValue.Record x -> x
    
    let json4 = 
        match json3 with
        [|(_,x)|] -> x
    

    val json4 : JsonValue = { "Id": "001", "Name": "A. N. Other",
    "IdDatetime": "2017-11-11T13:10:00+00:00" }

    Edit

    On an array of jsonvalues this works the same, except you have to map the matching function over. For example:

    let jsonText2 = """
    {
    "record": {
        "235": {
            "Id": "001",
            "Name": "A. N. Other",
            "IdDatetime": "2017-11-11T13:10:00+00:00"
        },
        "255": {
            "Id": "005",
            "Name": "D. Other",
            "IdDatetime": "2017-11-11T13:10:00+00:00"
        }
      }
    }
    """
    
    let json1 = JsonValue.Parse(jsonText2)
    let json2 = json1?record
    
    let json3 = 
        match json2 with
            | JsonValue.Record x -> x
    
    
    let json4 = 
    json3 
    |> Array.map (function _,x -> x) 
    

    val json4 : JsonValue [] = [|{ "Id": "001", "Name": "A. N. Other", "IdDatetime": "2017-11-11T13:10:00+00:00" }; { "Id": "005", "Name": "D. Other", "IdDatetime": "2017-11-11T13:10:00+00:00" }|]