intros.
unfold string_eqb.
destruct (String.string_dec s s); congruence.
Qed.
Fixpoint json_eqb (j j' : json.t) : bool :=
let fix loop_arr (l l': list json.t) : bool :=
match (l, l') with
| ([], []) => true
| (j :: l, j' :: l') => andb (json_eqb j j') (loop_arr l l')
| (_, _) => false
end in
let fix loop_obj (l l' : list (String.string * json.t)) : bool :=
match (l, l') with
| ([], []) => true
| ((s, j) :: l, (s', j') :: l') => andb (string_eqb s s')
(andb (json_eqb j j')
(loop_obj l l'))
| (_, _) => false
end in
match (j, j') with
| (json.Null, json.Null) => true
| (json.Bool b, json.Bool b') => Bool.eqb b b'
| (json.Num n, json.Num n') => Nat.eqb n n'
| (json.String s, json.String s') => string_eqb s s'
| (json.Arr l, json.Arr l') => loop_arr l l'
| (json.Obj l, json.Obj l') => loop_obj l l'
| _ => false
end.
Definition loop_arr :=
fix loop_arr (l l': list json.t) : bool :=
match (l, l') with
| ([], []) => true
| (j :: l, j' :: l') => andb (json_eqb j j') (loop_arr l l')
| (_, _) => false
end.
Definition loop_obj :=
fix loop_obj (l l' : list (String.string * json.t)) : bool :=
match (l, l') with
| ([], []) => true
| ((s, j) :: l, (s', j') :: l') => andb (string_eqb s s')
(andb (json_eqb j j') (loop_obj l l'))
| (_, _) => false
end.

(* Specifications: *)
Lemma json_eqb_eq : forall j j', json_eqb j j' = true -> j = j'.
Proof using.