A text diff of two JSON documents is mostly noise. Reformatting, a changed key order or a single inserted array element shifts every line that follows, and the output claims forty lines changed when one value changed. The question being asked is almost always "which fields differ", and that is a question about the parsed structure rather than about the bytes. So both documents are parsed and walked, and the report is a list of paths: what was added, what was removed, and what changed from which value to which.
Key order is irrelevant by construction, because objects are compared key by key. Formatting is irrelevant for the same reason. A type change is reported separately from a value change, and the walk stops descending once the types differ — an object becoming an array is one change, not every key removed and every index added, which is what a naive recursion produces and what makes its output unreadable.
Arrays compare by position by default, which is right when the array is ordered: a pipeline, a sequence of steps, a list of migrations. When it is really a set — tags, roles, permissions — position is meaningless and a reorder reports as every element changing. That case has a switch, and it matches elements by value instead, including whole objects. It is an option rather than a default because only you know which kind of array you have.