JsonProvider< ...> .Root没有null作为适当的值

时间:2017-09-01 19:09:30

标签: f# f#-data

我正在尝试查询已解析的Json的结果,如果我找不到,我想做其他事情。

[
  {
    "orderId": 136,
    "quantity": 5,
    "price": 3.75
  },
  {
    "orderId": 129,
    "quantity": 9,
    "price": 3.55
  },
  {
    "orderId": 113,
    "quantity": 11,
    "price": 3.75
  }
]

我的代码就像:

type OrdersProvider = JsonProvider<"Orders.json">
let orders = OrdersProvider.GetSamples()

let test id =
    let res = query{
                    for i in orders do
                        where (i.OrderId = id)
                        select i
                        headOrDefault
                }

    if isNull(res)
        then NOT_FOUND("")
        else OK(res.JsonValue.ToString())
    )

但是我收到编译错误“JsonProvider&lt; ...&gt; .Root没有null作为正确的值”。哪个是有道理的,除了我还想抓住id不在文件中的情况。我想我可以将headOrDefault更改为head并捕获异常,但想知道是否有更好的东西。

更新#1: 按照评论中的其中一个链接,我就可以逃脱

    if obj.ReferenceEquals(res,null)
        then NOT_FOUND("")
        else OK(res.JsonValue.ToString())
    )

更新#2: 虽然提到的代码有效,但仍然觉得语言不自然。接受的答案看起来更自然。

1 个答案:

答案 0 :(得分:2)

我认为headOrDefault操作是为了与LINQ to SQL的兼容性而设计的,这就是为什么它在默认情况下返回null - 这不是你通常想要的表现良好的东西F#代码,所以在你的查询方式中使用它不是一个好主意。

幸运的是,headOrDefault将使用F#选项类型 - 如果您从Some子句返回select,那么headOrDefault会返回None可用的:

let res = 
  query {
    for i in orders do
    where (i.OrderId = id)
    select (Some i)
    headOrDefault }

现在您可以使用模式匹配来处理缺少的案例:

match res with
| None -> NOT_FOUND("")
| Some order -> OK(order.JsonValue.ToString())