2012-01-08 15 views
2

我想使用webclient模块来查询couchDB休息接口(我使用它而不是opa couchdb API,因为我需要获得特定数量的文档)。解析一个webclient.Result内容在OPA

这里是用来做查询代码:

listmydocs(dburi)= 
match WebClient.Get.try_get(dburi) with 
     | { failure = _ } -> print("error\n") 
     | {success=s} -> match WebClient.Result.get_class(s) with 
      | {success} -> print("{s.content}")        
      | _   -> print("Error {s.code}") 
     end 

在s.content给出的结果是以下字符串:

{"total_rows":177,"offset":0,"rows":[ 
{"id":"87dc6b6d9898eff09b1c8602fb00099b","key":"87dc6b6d9898eff09b1c8602fb00099b","value":{"rev":"1-853bd502e3d80d08340f72386a37f13a"}}, 
{"id":"87dc6b6d9898eff09b1c8602fb000f17","key":"87dc6b6d9898eff09b1c8602fb000f17","value":{"rev":"1-4cb464c6e1b773b9004ad28505a17543"}} 
]} 

我想知道什么将是最好的方法解析这个字符串得到例如id列表,或者只有行字段? 我试图使用Json.deserialize(s.content),但不知道从那里去哪里。

回答

3

你可以有几个办法,OPA 2个反序列化的Json字符串:

1 - 第一个是简单地使用Json.deserialize接受一个字符串,按照到JSON规范产生一个JSON AST。 然后你可以匹配产生的AST来检索你想要的信息。

match Json.deserialise(a_string) with 
| {none} -> /*Error the string doesn't respect json specification*/ 
| {some = {Record = record}} -> 
/* Then if you want 'total_rows' field */ 
    match List.assoc("total_rows", record) with 
    | {some = {Int = rows}} -> rows 
    | {none} -> /*Unexpected json value*/ 

2 - 另一种方法是使用Json的“magic”opa deserilization。首先定义对应于期望值的Opa类型。然后使用OpaSerialize。*函数。根据你的例子

type result = { 
    total_rows : int; 
    offset : int; 
    rows : list({id:string; key:string; value:{rev:string}}) 
} 
match Json.deserialize(a_string) 
| {none} -> /*Error the string doesn't respect json specification*/ 
| {some = jsast} -> 
    match OpaSerialize.Json.unserialize_unsorted(jsast) with 
    | {none} -> /*The type 'result' doesn't match jsast*/ 
    | {some = (value:result) /*The coercion is important, it give the type information to serialize mechanism*/} -> 
    /* Use value as a result record*/ 
    value.total_rows 
+1

谢谢,“魔术”opa反序列化方法绝对是我正在寻找的。 – jeant 2012-01-09 09:55:19