如何使用 Yojson 遍历 JSON 对象中的 keys/members?
How do you iterate through the keys/members in a JSON object using Yojson?
到目前为止,我能看到的关于处理 json 对象的唯一示例涉及事先知道密钥,但我如何才能通过 keys/members 并单独处理它们的值?
假设您已经创建了一个 json
实例,也许通过使用 Yojson.Basic.from_channel (open_in filename)
从文件中读取或使用 Yojson.Basic.from_string string
从字符串中读取,然后您可以将其转换为关联列表使用 Yojson.Basic.Util.to_assoc
并像这样递归迭代它:
open Yojson.Basic
let iter js =
let rec f (nm,j) =
Printf.printf "\"%s\": " nm;
match j with
| `Assoc a ->
Printf.printf "assoc\n";
List.iter f a
| `Bool b ->
Printf.printf "bool: %b\n" b
| `Float f ->
Printf.printf "float: %f\n" f
| `Int i ->
Printf.printf "int: %d\n" i
| `List jl ->
Printf.printf "list: [";
List.iter (List.iter f) (List.map Util.to_assoc jl);
Printf.printf "]\n"
| `Null ->
Printf.printf "null\n"
| `String s ->
Printf.printf "string: \"%s\"\n" s in
List.iter f (Util.to_assoc js)
此 iter
函数首先将其 js
参数转换为关联列表,然后使用函数 f
对其进行迭代。 f
函数接受字符串和 json
类型的元组参数。为了这个例子,它打印字符串,然后匹配 json
类型并相应地对其进行操作。请注意 f
如何递归地处理 `Assoc
和 `List
变体的值。
Yojson 旨在用作 atdgen 的运行时。 Atdgen 通过将 JSON 数据转换为您的 OCaml 类型的数据,反之亦然,为用户节省了大量时间。
solution for JSON objects representing association lists 如下(示例源文件 assoc.atd
):
type t = (string * foo) list <json repr="object">
type foo = {
x: int;
y: int;
}
t
类型的样本数据 JSON 格式:
{
"p1": { "x": 1, "y": 2 },
"p2": { "x": 14, "y": 0 },
"q": { "x": 9, "y": -1 }
}
本例生成的界面为:
(* This is file assoc_j.mli derived from assoc.atd.
It provides the serializers and deserializers for JSON.
Other files are generated for other purposes,
including assoc_t.mli which contains only the OCaml
type definitions.
*)
type foo = Assoc_t.foo = { x: int; y: int }
type t = Assoc_t.t
val write_foo :
Bi_outbuf.t -> foo -> unit
(** Output a JSON value of type {!foo}. *)
val string_of_foo :
?len:int -> foo -> string
(** Serialize a value of type {!foo}
into a JSON string.
@param len specifies the initial length
of the buffer used internally.
Default: 1024. *)
val read_foo :
Yojson.Safe.lexer_state -> Lexing.lexbuf -> foo
(** Input JSON data of type {!foo}. *)
val foo_of_string :
string -> foo
(** Deserialize JSON data of type {!foo}. *)
val write_t :
Bi_outbuf.t -> t -> unit
(** Output a JSON value of type {!t}. *)
val string_of_t :
?len:int -> t -> string
(** Serialize a value of type {!t}
into a JSON string.
@param len specifies the initial length
of the buffer used internally.
Default: 1024. *)
val read_t :
Yojson.Safe.lexer_state -> Lexing.lexbuf -> t
(** Input JSON data of type {!t}. *)
val t_of_string :
string -> t
(** Deserialize JSON data of type {!t}. *)
到目前为止,我能看到的关于处理 json 对象的唯一示例涉及事先知道密钥,但我如何才能通过 keys/members 并单独处理它们的值?
假设您已经创建了一个 json
实例,也许通过使用 Yojson.Basic.from_channel (open_in filename)
从文件中读取或使用 Yojson.Basic.from_string string
从字符串中读取,然后您可以将其转换为关联列表使用 Yojson.Basic.Util.to_assoc
并像这样递归迭代它:
open Yojson.Basic
let iter js =
let rec f (nm,j) =
Printf.printf "\"%s\": " nm;
match j with
| `Assoc a ->
Printf.printf "assoc\n";
List.iter f a
| `Bool b ->
Printf.printf "bool: %b\n" b
| `Float f ->
Printf.printf "float: %f\n" f
| `Int i ->
Printf.printf "int: %d\n" i
| `List jl ->
Printf.printf "list: [";
List.iter (List.iter f) (List.map Util.to_assoc jl);
Printf.printf "]\n"
| `Null ->
Printf.printf "null\n"
| `String s ->
Printf.printf "string: \"%s\"\n" s in
List.iter f (Util.to_assoc js)
此 iter
函数首先将其 js
参数转换为关联列表,然后使用函数 f
对其进行迭代。 f
函数接受字符串和 json
类型的元组参数。为了这个例子,它打印字符串,然后匹配 json
类型并相应地对其进行操作。请注意 f
如何递归地处理 `Assoc
和 `List
变体的值。
Yojson 旨在用作 atdgen 的运行时。 Atdgen 通过将 JSON 数据转换为您的 OCaml 类型的数据,反之亦然,为用户节省了大量时间。
solution for JSON objects representing association lists 如下(示例源文件 assoc.atd
):
type t = (string * foo) list <json repr="object"> type foo = { x: int; y: int; }
t
类型的样本数据 JSON 格式:
{ "p1": { "x": 1, "y": 2 }, "p2": { "x": 14, "y": 0 }, "q": { "x": 9, "y": -1 } }
本例生成的界面为:
(* This is file assoc_j.mli derived from assoc.atd. It provides the serializers and deserializers for JSON. Other files are generated for other purposes, including assoc_t.mli which contains only the OCaml type definitions. *) type foo = Assoc_t.foo = { x: int; y: int } type t = Assoc_t.t val write_foo : Bi_outbuf.t -> foo -> unit (** Output a JSON value of type {!foo}. *) val string_of_foo : ?len:int -> foo -> string (** Serialize a value of type {!foo} into a JSON string. @param len specifies the initial length of the buffer used internally. Default: 1024. *) val read_foo : Yojson.Safe.lexer_state -> Lexing.lexbuf -> foo (** Input JSON data of type {!foo}. *) val foo_of_string : string -> foo (** Deserialize JSON data of type {!foo}. *) val write_t : Bi_outbuf.t -> t -> unit (** Output a JSON value of type {!t}. *) val string_of_t : ?len:int -> t -> string (** Serialize a value of type {!t} into a JSON string. @param len specifies the initial length of the buffer used internally. Default: 1024. *) val read_t : Yojson.Safe.lexer_state -> Lexing.lexbuf -> t (** Input JSON data of type {!t}. *) val t_of_string : string -> t (** Deserialize JSON data of type {!t}. *)