Brotli wins because it uses a predefined dictionary of 120 KiB in size in addition to typical sliding window dictionary.The dictionary contains over 13k words, phrases and other substrings derived text and HTML documents.
Zstandard can use a user-provided compression dictionary. It has training mode to generate those.
My hypothesis is that JSON->Zstd->JSON would win if you would give Zstd equivalent dictionary. Trained with application specific dictionary would be even faster.