Reputation: 1937
I am trying to consume an API which return a JSON built as :
Team.player1 / player2 / player3... (the players are built as properties and not as an array)
I was thinking to use reflection to do it, but having hard time to get a player.
type Simple = JsonProvider<"sample.json">
let wbReq = "API-FOR-TEAM"
let docAsync = Simple.Load(wbReq)
let allValues = FSharpType.GetRecordFields (docAsync.Team.Players.GetType())
let test = allValues
|> Seq.map (fun p -> (p.GetValue(docAsync.Team.Players) as ?).Name) // HOW TO GET THE TYPED PLAYER HERE ?
|> fun p -> printfn p
EDIT : I tried to use GetType and System.Convert.ChangeType
EDIT2 : Here is a simplified version of the JSON :
{
"Team": {
"id": "8",
"players": {
"17878": {
"info": {
"idteam": 8,
"idplayer": 17878,
"note": 6
}
},
"18507": {
"info": {
"idteam": 8,
"idplayer": 18507,
"note": 5
}
}
}
}
}
Edit 3 :
I found an easy solution in C# (thanks to JSON.net and dynamic) but for learning purpose I would like to do the same in F# if someone wanna help :
private static List<Player> Parse(string jsonString)
{
dynamic jsonObject = JsonConvert.DeserializeObject(jsonString);
var players = ParseItems(jsonObject.Home.players);
return players;
}
private static List<Player> ParseItems(dynamic items)
{
List<Player> itemList = new List<Player>();
foreach (var item in items)
{
itemList.Add(new Player()
{
idplayer = item.Value.info.idplayer,
lastName = item.Value.info.lastname,
note = item.Value.info.note
});
}
return itemList;
}
Upvotes: 3
Views: 284
Reputation: 2220
You can mix JsonTypeProvider and parsing Json. For example:
[<Literal>]
let sample = """{
"Team": {
"id": "8",
"players": {
"17878": {
"info": {
"idteam": 8,
"idplayer": 17878,
"note": 6
}
},
"18507": {
"info": {
"idteam": 8,
"idplayer": 18507,
"note": 5
}
}
}
}
}"""
type Player = {IdTeam:int; IdPlayer:int; Note:int}
type Simple = JsonProvider<sample>
let docAsync = Simple.GetSample()
let json = docAsync.Team.Players.JsonValue
let parseInfo (json:JsonValue) =
let id_team = (json.GetProperty "idteam").AsInteger()
let id_player = (json.GetProperty "idplayer").AsInteger()
let note = (json.GetProperty "note").AsInteger()
{IdTeam = id_team; IdPlayer = id_player; Note = note}
let players =
json.Properties()
|> Array.map(fun (_,x) -> x.GetProperty "info")
|> Array.map (parseInfo)
players
|> Array.iter (printfn "%A")
Upvotes: 1