The symptom looks like database corruption: save text with an em dash — or a letter like š somewhere in WordPress, and the next time you look, it reads literally “u2014” or “u0161” instead of the character. The database is fine — the cause is narrower, and far more common, than it looks.
The Symptom
It usually shows up first wherever someone types a special character by hand — a contact-form placeholder, a product title, imported content. Everything looks correct in the admin while you’re saving it; refresh the page and the character is gone, replaced by a bare hex code.
Two Mechanisms That Don’t Agree
json_encode() — and WordPress’s own wp_json_encode() wrapper — escapes every non-ASCII character as a \u sequence by default: an em dash becomes \u2014, š becomes \u0161. That’s correct, standard JSON.
The problem happens a step later. add_post_meta(), update_post_meta(), and update_option() all call wp_unslash() on the value internally before saving — the mechanism that reverses WordPress’s automatic escaping of $_POST data. wp_unslash() can’t tell the difference between a backslash WordPress added itself and a backslash that’s part of your JSON: it strips both. \u2014 becomes literally u2014.
The Fix
The fix is one line, not a rewrite: json_encode($data, JSON_UNESCAPED_UNICODE) so the character stays a real character instead of an escape, plus wp_slash() around the whole call before handing it to update_post_meta(), so unslash has something harmless to strip instead of your content.
Where Else It Hides
Anything that JSON-encodes data before saving it into a meta field or option is a candidate — form builders, content importers, custom fields. The bug passes tests unnoticed because test data rarely contains diacritics or an em dash, so it only shows up the first time someone actually writes real Croatian or German text.
A bug the English-speaking web almost never finds — one š or one em dash is enough to make it visible.