Потому что вы задаёте строку напрямую в коде. Из кода
описание строки вида
'{ foo: "b\"ar" }'
превращается в памяти в
строку { foo: "b"ar" }
после чего JSON.parse, пытаясь её распарсить, естественно, спотыкается.
Когда вы получаете ajax ответ от сервера вида
{ foo: "b\"ar" }
сразу строкой, он именно таком виде и идёт в память.
Если хотите получить строку содержащую символы экранирования - эти символы также надо заэкранировать:
blocks: JSON.parse('[{"type":"header","data":{"text":"Тест","level":1}},{"type":"paragraph","data":{"text":"Тут вот <a href=\\"https://wordpress.org/plugins/woo-variations-style-buttons/\\">ссылка</a>."}}]')