Can you return the parsed JSONProvider result as a Model object to use in the view for MVC?

StackOverflow https://stackoverflow.com/questions/17395790

  •  02-06-2022
  •  | 
  •  

Pergunta

So I have the following F# method

static member ReadInstagramSearch() =
    let data = Http.Request( "https://api.instagram.com/v1/users/search?q=SomeUSer&client_id=someclientid" )
    let res = FsUserSearch.Parse(data)

    res.Data.[0]

If I have a C# controller that I call this method with is there anyway to use that result in the View? I've tried just simple access with

@Model.FirstName

but that gives me an exception

'FSharp.Data.RuntimeImplementation.JsonDocument' does not contain a definition for 'FirstName'

Is my only option to turn that JsonDocument into a strongly typed Model object? And then return that?

This is using http://fsharp.github.io/FSharp.Data/library/JsonProvider.html

And my JsonProvider is defined as

type FsUserSearch = JsonProvider<"""
{
    "data": [{
        "username": "jack",
        "first_name": "Jack",
        "profile_picture": "http://distillery.s3.amazonaws.com/profiles/profile_66_75sq.jpg",
        "id": "66",
        "last_name": "Dorsey"
    }]
}""">
Foi útil?

Solução

Sadly, this is not supported at the moment. The JSON type provider uses erased types which means that the parsed document is represented as a value of type JsonDocument that does not actually have any of the members that you can see in F#. The F# compiler understands this, but they are not present in compiled code and other languages do not support type providers at the moment.

There is a number of ways to fix this and it is certainly on the TODO list. (It is a bit tricky, implementing ICustomTypeDescriptor would work in some scenarios, but not here. Generating actual types might be a way forward. For more information, see this bug at F# Data GitHub page.)

For now, you might be able to use the dynamic access operations that the JSON library provides. See the JSON Parser and Reader page for more details. I think @Model.FirstName could be done using:

@Model.GetProperty("FirstName").AsString()

Certainly not perfect - but sadly C# does not support type providers, so this is probably the best option. Another workaround would be to define a simple F# record type and transform the data you need into a record type that you can then easily use from C#.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top