В настоящее время я пытаюсь использовать F # JsonProvider для десериализации набора объектов Json, которые я получаю от REST API.
Это уже работает для большей части части, но объекты содержат вложенный элемент, которыйможет иметь разное содержание.
Когда-то это может быть обычный JsonObject, как в
{
"dataType": "int",
"constraints": {
"min": 0,
"max": 650,
"scaling": -10,
"steps": 1
},
"defaultValue": "string",
}
, но это также может быть многомерный массив, как в
{
"dataType": "enum",
"constraints": {
"names": [["n.a.", 1],
["OK", 4],
["High Warn", 6],
["Too Low", 7],
["Too High", 8],
["Low Warn", 9]]
},
"defaultValue": "4",
}
В типе, который я 'При условии, что я хотел бы раскрыть ограничения следующим образом:
type Description (descriptionJsonIn: string) =
let parsedInfo = DescriptionProvider.Parse(descriptionJsonIn)
let parsedConstraints =
match parsedInfo.Constraints.JsonValue.Properties().[0].ToString() with
//| "names" ->
//parsedInfo.Constraints.JsonValue.Properties
//|> Array.map (fun x -> x.ToValueTuple)
//|> dict<string,string>
| "min" ->
parsedInfo.Constraints.JsonValue.Properties()
|> Seq.map (fun (k,v) -> k,v.AsString())
|> dict
| "maxLength" ->
parsedInfo.Constraints.JsonValue.Properties()
|> Seq.map (fun (k,v) -> k,v.AsString())
|> dict
| _ -> dict["",""]
member __.DataType = parsedInfo.DataType
member __.DefaultValue = parsedInfo.DefaultValue
member __.Constraints = parsedConstraints
У меня такое ощущение, что решение должно быть похоже на (недействительное)
| "names" ->
parsedInfo.Constraints.JsonValue.Properties()
|> Seq.map (fun (x) -> fst(x.ToValueTuple()).ToString(), snd(x.ToValueTuple()).ToString() )
|> dict<string,string>
, но я не знаюдостаточно синтаксиса F # для продолжения поиска.Я продолжаю получать одни и те же результаты :(
Вопросы теперь: как мне перейти от parsedInfo.Constraints.JsonValue.Properties()
к словарю, который я хотел бы вернуть?
[ОБНОВЛЕНИЕ после принятого ответа]
Принятый ответ был и является правильным, однако из-за меняющегося требования мне пришлось немного подправить, поскольку существует более одного типа ограничения, представленного с несколькими свойствами.
В итоге я набрал
let objectConstraints =
let c = parsedVariableDescription.Constraints
if c.ToString().Contains("\"min\":")
then
[
"Min", c.Min
"Max", c.Max
"Scaling", c.Scaling
"Steps", c.Steps
]
|> Seq.choose (fun (n, v) -> v |> Option.map (fun v -> n, v.ToString()))
else if c.ToString().Contains("\"maxLen\":")
then
[
"RegExpr", c.RegExpr
"MaxLen", c.MaxLen
]
|> Seq.choose (fun (n, v) -> v |> Option.map (fun v -> n, v.ToString()))
else
Seq.empty
let namedConstraints =
parsedVariableDescription.Constraints.Names
|> Seq.map (fun arr ->
match arr.JsonValue.AsArray() with
| [| n; v |] -> n.AsString(), v.AsString()
| _ -> failwith "Unexpected `names` structure")
Я в порядке, возвращая все как строку в данный момент, так как часть, которая будет использовать результат, должна все равно иметь дело с преобразованием данных.