如何使用OCaml Url和Cohttp

时间:2013-11-19 03:32:25

标签: json api http url ocaml

我正在尝试使用OCaml的Url和Cohttp模块来访问API并检索JSON数据。我不是试图以异步方式执行此操作。我没有网络/网络编程的经验,所有的模块文档只提供类型和方法的签名(对我来说没什么帮助,因为我不知道他们做了什么)。我正在尝试访问bitstamp API并检索比特币的出价。到目前为止,我只知道如何声明URI

    let bitstamp_uri = Uri.of_string "http://www.bitstamp.net/api/ticker/";;

但我现在知道如何调用uri以检索json数据。如何使用现有库来完成此任务?我已经知道如何将json数据解析为我需要的类型。

4 个答案:

答案 0 :(得分:4)

Cohttp要求您使用Lwt或Async,因此您必须学习其中一个库。幸运的是,检索JSON文本并解析它正是新的Real World OCaml书中的一个例子,您可以在线免费阅读here。第18章介绍了Async和Cohttp,第15章介绍了JSON解析。

现在,要真正回答你的问题:

$ utop
utop # #require "lwt.syntax";;
utop # #require "core";;
utop # open Core.Std;;
utop # #require "cohttp.lwt";;
utop # #require "uri";;

utop # let get_uri uri : string Or_error.t Lwt.t =
  let open Lwt in
  match_lwt Cohttp_lwt_unix.Client.get uri with
  | None ->
    let msg = sprintf "%s: no reply" (Uri.to_string uri) in
    return (Or_error.error_string msg)
  | Some (_, body) -> (
      lwt body = Cohttp_lwt_body.string_of_body body in
      return (Ok body)
    );;

utop # let bitstamp_uri = Uri.of_string "http://www.bitstamp.net/api/ticker/";;

utop # get_uri bitstamp_uri;;
- : string Or_error.t =
Core_kernel.Result.Ok
"{\"high\": \"755.00\", \"last\": \"675.20\", \"timestamp\": \"1384841189\", \"bid\": \"675.10\", \"volume\": \"72858.24608402\", \"low\": \"471.26\", \"ask\": \"675.20\"}" 

在这种情况下我使用了Core和Lwt。 RWO书籍使用Async。如果你想完全避免异步编程的复杂性,那么就不能使用Cohttp。

答案 1 :(得分:2)

以下是使用Curl的答案,不需要您了解异步。 (为了记录,我认为你最好不要使用Async和Cohttp!)

(* Wrapper for Curl. Used by the function below. *)
let fetch (url: string) (f: string -> int): unit =
  let c = Curl.init () in
  Curl.set_url c url;
  Curl.set_followlocation c true;
  Curl.set_writefunction c f;
  Curl.perform c;
  Curl.cleanup c
;;

(* [get url] fetches the document at [url] and returns its contents as a string. *)
let get (url: string): string =
  let buf = Buffer.create 16 in
  fetch url (fun s -> Buffer.add_string buf s; String.length s);
  Buffer.contents buf
;;

答案 2 :(得分:2)

这是您可能觉得有用的另一个例子。在这个例子中,我不依赖于Core或Async,你应该能够将它作为脚本运行而不是在顶层运行。

#! /usr/bin/env ocaml

#use "topfind"
#require "uri"
#require "cohttp.lwt"

let fetch uri =
  let open Lwt in
  Cohttp_lwt_unix.Client.get uri >>= fun (resp, body) ->
  Cohttp_lwt_body.to_string body >>= fun b ->
  Lwt_io.printl b

let () =
  let bitstamp_uri = Uri.of_string "http://www.bitstamp.net/api/ticker/" in
  Lwt_main.run (fetch bitstamp_uri)

答案 3 :(得分:0)

utop [0]: #require "async";;
utop [1]: #require "cohttp.async";;
utop [2]: open Async.Std;;
utop [3]:  let get_uri uri_str = Cohttp_async.Client.get @@ Uri.of_string uri_str
>>= fun (_, body) -> Cohttp_async.Body.to_string body;;
val get_uri : string -> string Deferred.t = <fun>
utop [4]: get_uri "http://www.bitstamp.net/api/ticker/";;
- : string = "{\"high\": \"661.11\", \"last\": \"652.65\", \"timestamp\": 
\"1402207587\", \"bid\": \"651.99\", \"vwap\": \"654.52\", \"volume\": 
\"3022.07902416\", \"low\": \"648.87\", \"ask\": \"654.29\"}"

我需要一段时间来弄明白,所以我只是在这里发布代码。