···12091209 | _ -> tree)
12101210 | _ -> tree)
1211121112121212+(** Build a filtered subtree of [doc] keeping only branches that match one of
12131213+ [paths]. Walks [doc] structurally so arrays stay arrays and only the kept
12141214+ positions are populated; the array's intermediate items are kept as-is when
12151215+ a deeper path passes through them. *)
12121216let json_filter doc paths =
12131213- List.fold_left
12141214- (fun acc path ->
12151215- match json_lookup doc path with
12161216- | Some v -> json_insert acc path v
12171217- | None -> acc)
12181218- (Value.Object []) paths
12171217+ let rec walk doc paths =
12181218+ if List.mem [] paths then doc
12191219+ else
12201220+ match doc with
12211221+ | Value.Object pairs ->
12221222+ let kept =
12231223+ List.filter_map
12241224+ (fun (k, v) ->
12251225+ let key =
12261226+ match k with
12271227+ | Value.String s -> s
12281228+ | Value.Number n -> string_of_float_int n
12291229+ | _ -> ""
12301230+ in
12311231+ let sub_paths =
12321232+ List.filter_map
12331233+ (function p :: rest when p = key -> Some rest | _ -> None)
12341234+ paths
12351235+ in
12361236+ if sub_paths = [] then None else Some (k, walk v sub_paths))
12371237+ pairs
12381238+ in
12391239+ Value.Object kept
12401240+ | Value.Array xs ->
12411241+ List.mapi
12421242+ (fun i v ->
12431243+ let key = string_of_int i in
12441244+ let sub_paths =
12451245+ List.filter_map
12461246+ (function p :: rest when p = key -> Some rest | _ -> None)
12471247+ paths
12481248+ in
12491249+ if sub_paths = [] then None else Some (walk v sub_paths))
12501250+ xs
12511251+ |> List.filter_map (fun x -> x)
12521252+ |> fun ys -> Value.Array ys
12531253+ | _ -> doc
12541254+ in
12551255+ walk doc paths
1219125612201257let json_remove doc paths =
12211258 List.fold_left (fun acc path -> json_delete acc path) doc paths