Можно ли спарсить Json с не экранированными кавычками?
Можно попробовать исправить поломанный JSON.Примерно так, но это не покрывает 100% случаев из вашего вопроса<?php
$str = '{"name": "my "name"", "value": "123456789"}';

function fixJSON($str) {
    $len = strlen($str);
    $result = '';
    $space = '';
    $mode = 0;
    for($i=0;$i<$len;$i++){
        $c = $str[$i];
        switch ($mode) {
            case 0: //вне строки
                if ($c == '"') $mode = 1;
                $result .= $c;
                break;
            case 1: //внутри строки
                if ($c == '"') {
                    $mode = 3;
                    $space = $c;
                    break;
                }
                if ($c == '\\') $mode = 2;
                $result .= $c;
                break;
            case 2: //сразу после слеша (игнорим один любой символ)
                $mode = 1;
                $result .= $c;
                break;
            case 3: //была кавычка внутри строки
                if ($c == ' ' || $c == '\n' || $c == '\t' || $c == '\r')
                    $space .= $c;
                elseif ($c == ',' || $c == '}' || $c == ']' || $c == ':') {
                    //вероятно был конец строки (шанс 99%)
                    $mode = 0;
                    $result .= $space.$c;
                } else {
                    //мы остались внутри строки на 100%. Экранируем
                    $mode = 1;
                    $result .= '\\'.$space;
                    $i--; //уходим назад, т.к. вдруг это снова кавычка
                }
                break;
        }
    }
    return $result;
}

echo(fixJSON($str)); //{"name": "my \"name\"", "value": "123456789"}
?>
Но лучше исправить то место, которое приводит к поломке JSON, чтобы оттуда к вам сразу нормальные строки приходили, а не костыли изобретать.
P.S.Более совершенный и более упоротый вариант<?php
$str = '{"say": ""my name", hi", "value": "123456789"}';

function fixJSON($str) {
    $len = strlen($str);
    $result = '';
    $space = '';
    $mode = 0;
    for($i=0;$i<$len;$i++){
        $c = $str[$i];
        switch ($mode) {
            case 0: //вне строки
                if ($c == '"') $mode = 1;
                $result .= $c;
                break;
            case 1: //внутри строки
                if ($c == '"') {
                    $mode = 3;
                    $space = $c;
                    break;
                }
                if ($c == '\\') $mode = 2;
                $result .= $c;
                break;
            case 2: //сразу после слеша (игнорим один любой символ)
                $mode = 1;
                $result .= $c;
                break;
            case 3: //была кавычка внутри строки
                if ($c == ' ' || $c == '\n' || $c == '\t' || $c == '\r')
                    $space .= $c;
                elseif ($c == '}' || $c == ']') {
                    //вероятно был конец строки (шанс 99%)
                    $mode = 4;
                    $space .= $c;
                }
                elseif ($c == ',' || $c == ':') {
                    //вероятно был конец строки (шанс 90%)
                    $mode = 5;
                    $space .= $c;
                } else {
                    //мы остались внутри строки на 100%. Экранируем
                    $mode = 1;
                    $result .= '\\'.$space;
                    $i--; //уходим назад, т.к. вдруг это снова кавычка
                }
                break;
            case 4: //после спец символа
                if ($c == ' ' || $c == '\n' || $c == '\t' || $c == '\r')
                    $space .= $c;
                elseif ($c == ',') {
                    //был конец строки с шансом 99.99%
                    $mode = 0;
                    $result .= $space.$c;
                } else {
                    //внтури строки на 100%
                    $mode = 1;
                    $result .= '\\'.$space;
                    $i--;
                }
                break;
            case 5: //после запятой
                if ($c == ' ' || $c == '\n' || $c == '\t' || $c == '\r')
                    $space .= $c;
                elseif (preg_match('/[0-9"-]+/', $c)) {
                    //был конец строки с шансом 99.9%
                    $mode = 0;
                    $result .= $space;
                    $i--;
                } else {
                    //внтури строки на 100%
                    $mode = 1;
                    $result .= '\\'.$space;
                    $i--;
                }
                break;
        }
    }
    if ($mode>2) $result .= $space;
    return $result;
}

echo(fixJSON($str)); //{"say": "\"my name\", hi", "value": "123456789"}
?>Но всегда можно в строку засунуть другой JSON и никакой конечный фиксер не справится с такой глубиной.
Нет