OCaml flat JSON decoder with entry-index errors

OCaml
exception Json_error of string
(* Decode a flat JSON object of string fields, reporting the failing entry. *)
let decode_flat src =
  let fail msg = raise (Json_error msg) in
  let s = String.trim src and n = String.length (String.trim src) in
  if n < 2 || s.[0] <> '{' || s.[n - 1] <> '}' then fail "expected an object {...}";
  if n = 2 then []
  else
    String.sub s 1 (n - 2)
    |> String.split_on_char ','
    |> List.mapi (fun i pair ->
        match String.index_opt pair ':' with
        | None -> fail (Printf.sprintf "entry %d: missing ':' in %S" i (String.trim pair))
        | Some k ->
          let key = String.trim (String.sub pair 0 k) in
          let raw = String.trim (String.sub pair (k + 1) (String.length pair - k - 1)) in
          let unquote what text =
            let m = String.length text in
            if m >= 2 && text.[0] = '"' && text.[m - 1] = '"' then Scanf.unescaped (String.sub text 1 (m - 2))
            else fail (Printf.sprintf "entry %d: %s must be a quoted string, got %S" i what text)
          in
          (unquote "key" key, unquote "value" raw))