Разбор F# JSON - Как получить свойство, используя сложный путь (состоящий из нескольких имен свойств)

Можно ли получить свойство из JSON, используя сложный путь, например "prop1.prop2"? Образец JSON, который я использовал:

{
    "prop1": {
        "prop2": "value"
    }
}

Я хочу получить собственность "prop2" там со своей ценностью "value": Когда я пытался:

#r "../packages/FSharp.Data.2.3.0/lib/net40/FSharp.Data.dll"
open FSharp.Data
open FSharp.Data.JsonExtensions

let json = JsonValue.Load "SampleJson.json"
json.GetProperty("prop1.prop2")

Я получил:

System.Exception: Didn't find property 'prop1.prop2' in {"prop1":{"prop2":"value"}}

Я пытался написать такой метод самостоятельно, но это выглядит неуклюже:

let rec tryGetChildValue (propNameSplitted : List<string>) (json:JsonValue) = 
    match propNameSplitted with
    | [] -> None
    | [x] -> json.TryGetProperty (x)
    | x::xs -> 
        match json.TryGetProperty (x) with
        | Some p -> tryGetChildValue xs (json.GetProperty(x))
        | None -> None

let tryGetPropValue (propName: string) (json:JsonValue) = 
    let s = propName.Split '.' |> Array.toList
    tryGetChildValue s json

let propName = "prop1.prop2"
let result = (tryGetPropValue propName json)

2 ответа

Решение

Вы можете сделать это тривиально с JSON.net:

open Newtonsoft.Json.Linq

let query json =
    let j = JObject.Parse json
    j.SelectToken "prop1.prop2" |> string

Очевидно, что в этом подходе нет безопасности типов, но это компромисс, если вы хотите выполнять запросы с использованием произвольных строк.

Внутри FSharp.Data вы можете найти JSonProvider это позволяет вам получать свойства (и больше, если хотите) из объекта JSON, используя сложный путь. Вы можете сделать что-то вроде этого, и это должно работать для вас:

type test =  FSharp.Data.JsonProvider<"""{
    "prop1": {
        "prop2": "value"
    }
} """>

let testSample = test.GetSample()

let testValue = testSample.Prop1.Prop2

и вы получите возвращаемое значение: val testValue : string = "value"

Вы должны быть осторожны, так как то, что вы даете в качестве параметра JSonProvider, является строковым представлением вашего объекта Json.

Надеюсь, это поможет:)

В 2020 вы можете использовать JsonValue.Parse из FSharp.Data.JsonExtensions, как это F# Data: JSON Parser

Другие вопросы по тегам