I am trying to query results of the parsed Json and if I cannot find I want to do something else.
[
{
"orderId": 136,
"quantity": 5,
"price": 3.75
},
{
"orderId": 129,
"quantity": 9,
"price": 3.55
},
{
"orderId": 113,
"quantity": 11,
"price": 3.75
}
]
My code is like:
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())
)
However I am getting compiler error "JsonProvider<...>.Root does not have null as proper value". Which is kinda makes sense except I still want to catch the case when id is not in the file. I guess I could change headOrDefault to head and trap the exception but wonder if there is something better.
Update #1: Following one of the links in comments I was able to get away with
if obj.ReferenceEquals(res,null)
then NOT_FOUND("")
else OK(res.JsonValue.ToString())
)
Update #2: While mentioned code works but still feels unnatural for the language. Accepted answer looks more natural.
I think the headOrDefault operation was designed for compatibility with LINQ to SQL, which is why it returns null in the default case - this is not something you'd normally want in well behaved F# code, so using it in the way your query does is not a good idea.
Fortunately, headOrDefault will work with F# option type - if you return Some from your select clause then headOrDefault returns None when the value is not available:
let res =
query {
for i in orders do
where (i.OrderId = id)
select (Some i)
headOrDefault }
Now you can handle the missing case with pattern matching:
match res with
| None -> NOT_FOUND("")
| Some order -> OK(order.JsonValue.ToString())
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With