我正在尝试使用OCaml的Url和Cohttp模块来访问API并检索JSON数据。我不是试图以异步方式执行此操作。我没有网络/网络编程的经验,所有的模块文档只提供类型和方法的签名(对我来说没什么帮助,因为我不知道他们做了什么)。我正在尝试访问bitstamp API并检索比特币的出价。到目前为止,我只知道如何声明URI
let bitstamp_uri = Uri.of_string "http://www.bitstamp.net/api/ticker/";;
但我现在知道如何调用uri以检索json数据。如何使用现有库来完成此任务?我已经知道如何将json数据解析为我需要的类型。
答案 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\"}"
我需要一段时间来弄明白,所以我只是在这里发布代码。