Instance tag_Serializer : Serializer t.(* json <-> tree tag conversion *)

    Fixpoint json_treeify (j : json.t) : tree tag.t :=
      let fix obj_list_to_tree_list (l : list (String.string * json.t)) :=
          match l with
          | [] => []
          | (s, j) :: l => atom (tag.Str s)
                                :: json_treeify j
                                :: obj_list_to_tree_list l
          end
      in
      match j with
      | json.Null => atom tag.Null
      | json.Bool b => atom (tag.Bool b)
      | json.Num n => atom (tag.Num n)
      | json.String s => atom (tag.Str s)
      | json.Arr l => node (atom tag.Arr :: List.map json_treeify l)
      | json.Obj l => node (atom tag.Obj :: obj_list_to_tree_list l)
      end.Definition obj_list_to_tree_list :=
      fix obj_list_to_tree_list (l : list (String.string * json.t)) :
        list (tree tag.t) :=
        match l with
        | [] => []
        | (s, j) :: l => atom (tag.Str s) :: json_treeify j :: obj_list_to_tree_list l
        end.Fixpoint json_untreeify (t : tree tag.t) : option json.t :=
      let fix untreeify_list (l : list (tree tag.t)) : option (list json.t) :=
          match l with
          | [] => Some []
          | x :: l => match json_untreeify x with
                      | None => None
                      | Some y => match untreeify_list l with
                                  | None => None
                                  | Some l => Some (y :: l)
                                  end
                      end
          end in
      let fix untreeify_obj_list (l : list (tree tag.t)) :
            option (list (String.string * json.t)) :=
          match l with
          | [] => Some []
          | atom (tag.Str s) :: t :: l =>
            match json_untreeify t with
            | None => None
            | Some j => match untreeify_obj_list l with
                        | None => None
                        | Some l => Some ((s, j) :: l)
                        end
            end
          | _ => None
          end in
      match t with
      | atom (tag.Num n) => Some (json.Num n)
      | atom (tag.Bool b) => Some (json.Bool b)
      | atom (tag.Str s) => Some (json.String s)
      | node (atom tag.Arr :: l) => match untreeify_list l with
                                    | None => None
                                    | Some l => Some (json.Arr l)
                                    end
      | atom (tag.Null) => Some (json.Null)
      | node (atom tag.Obj :: l) => match untreeify_obj_list l with
                                    | None => None
                                    | Some l => Some (json.Obj l)
                                    end
      | _ => None
      end.Definition untreeify_obj_list :=
      fix untreeify_obj_list (l : list (tree tag.t)) :
        option (list (String.string * json.t)) :=
        match l with
        | [] => Some []
        | atom (tag.Str s) :: t :: l =>
          match json_untreeify t with
          | None => None
          | Some j => match untreeify_obj_list l with
                      | None => None
                      | Some l => Some ((s, j) :: l)
                      end
          end
        | _ => None
        end.Definition untreeify_list :=
      fix untreeify_list l : option (list json.t) :=
        match l with
        | [] => Some []
        | x :: l => match json_untreeify x with
                    | None => None
                    | Some y => match untreeify_list l with
                                | None => None
                                | Some l => Some (y :: l)
                                end
                    end
        end.Definition treeify_untreeify_aux (j : json.t) :=
      json_untreeify (json_treeify j) = Some j.

Lemma treeify_untreeify_id : forall j : json.t, treeify_untreeify_aux j.