Json Type Provider -> using Load and credentials

398 views Asked by At

I am making the following request which is returning Json.

let baseUrl = "http://wex-qa.mybluemix.net/resources/question"
let userName = "[email protected]"
let password = "yourCreds"
let authKey = userName + ":" + password

let client = new HttpClient()
client.DefaultRequestHeaders.Authorization <- new AuthenticationHeaderValue("Basic",authKey)

let input = new Dictionary<string,string>()
input.Add("question","what time is it")
let content = new FormUrlEncodedContent(input)

let result = client.PostAsync(baseUrl,content).Result
let resultContent = result.Content.ReadAsStringAsync().Result

I immediately thought of using the Json Type Provider so I made a local file of the response to be the type def. I then went to load the type where I need the credentials and the content. However, I did not see where the .Load() function have an overload to pass in the credentials and the content. Should I continue to make the request via the HttpClient class and use the .Parse() function?

Thanks in advance.

1

There are 1 answers

0
Stephen Hosking On

Expanding on the answer in the comments (which is correct).

I had this problem in 2022 with FSharp.Data 4.2.9. There still seems to be no way to put authorisation credentials into the requests for either defining the JsonProvider type, or the runtime collection of data. With a bit of working around, it can be made to work like a type provider, as described in the question and comment.

  1. Get your credentials for web requests from the site. This often involves a single 'key' rather than a username/password pair.
  2. Instantiate the type provider with sample data from the site (extracted with the required credentials).
  3. At runtime, use HttpClient with Authorization, to read JSON from the URL, and then use the Parse method of the type provide to return typed data. This allows you to use intellisense on the returned data

This example is for the MailChimp API, which supports mailing lists and requires a company API Key on web requests.

First, follow instructions on the site to get 'Credentials' for API calls.

Second, use any method to extract sample JSON to a file. I used the PHP samples provided by MailChimp.

Then define the JsonProvider with that data.

type mcListsTypeProvider = JsonProvider< "./lists_sample_data.json">

Here lists is a fundamental component of the API. In this example, I will be working with the "Sales Subscribers" list.

The next function will read from a URL, and return typed Json data, as if directly from the Load function.

The core of this is the jsonProviderParse argument, which is the Parse method from the JsonProvider.

let loadTypedJson url jsonProviderParse =

    use httpClient = new HttpClient()

    // Set up authorisation
    let mailChimpApiKey = "3ef8dXXXXXXXXXXXXXXXXf61e-us18" // Could be a "userName:passowrd" key
    httpClient.DefaultRequestHeaders.Authorization <- AuthenticationHeaderValue("Basic",mailChimpApiKey)

    // Get content
    let result = httpClient.GetAsync(url : string).Result
    let content = result.Content.ReadAsStringAsync().Result

    // Parse content, with the Parse method from the JsonProvider
    jsonProviderParse content

Then use loadTypedJson as you would myTypeProvider.Load("https:..")

// Find the MailChimp list Id for the "Sales Subscribers" list

let listsUrl = "https://us18.api.mailchimp.com/3.0/lists"

let data = loadTypedJson listsUrl mcListsTypeProvider.Parse

let list_id = 
    data.Lists
    |> Seq.find (fun list -> list.Name = "Sale Subscribers")
    |> (fun x -> x.Id)


printfn "Sale Subscribers list_id = %s" list_id

Output: list_id = f21XXXXX85

Intellisense working for the JsonProvider

Intellisense working for the JsonProvider: