Как избежать JSON-строки, содержащей символы новой строки, используя JavaScript?

166

Я должен сформировать строку JSON, в которой значение имеет символ новой строки. Это должно быть экранировано, а затем опубликовано с помощью вызова AJAX. Может ли кто-нибудь предложить способ избежать строки с помощью JavaScript. Я не использую jQuery.

Srikant
источник
1
Я пытался экранировать символ новой строки \ n в \\ n. Работает нормально. Но я ищу любую библиотеку JS, которая может сделать это для всех escape-символов.
Срикант
1
Зачем вам нужно экранировать строки в JSON? Как эти значения декодируются, когда они используются, потому что подходящим решением является использование связанной функции кодирования.
zzzzBov
я потратил 6 часов, пробуя всевозможные вещи с множеством вариаций, но обнаружил, что крошечная дополнительная черта заставила бы все работать как по волшебству, то, что я считал трудным, заняло 5 минут ... то, что мне показалось, стало невозможным. .omg
Мухаммед Умер
1
Когда вы используете Ajax-вызовы с php-db-save на стороне сервера, просто используйте php-функцию addlashes () для его преобразования. С этим решением у вас есть только одно место для преобразования, и оно чище, чем строки javascript-replace.
Марсель Энникс
См. Соответствующий ответ и решение на http://stackoverflow.com/questions/30366324/unescape-special-characters-in-ajax-response-data
kofifus

Ответы:

135

Возьми свой JSON и .stringify()все. Затем используйте .replace()метод и заменить все вхождения \nс \\n.

РЕДАКТИРОВАТЬ:

Насколько я знаю, нет известных библиотек JS для экранирования всех специальных символов в строке. Но вы можете связать .replace()метод и заменить все специальные символы следующим образом:

var myJSONString = JSON.stringify(myJSON);
var myEscapedJSONString = myJSONString.replace(/\\n/g, "\\n")
                                      .replace(/\\'/g, "\\'")
                                      .replace(/\\"/g, '\\"')
                                      .replace(/\\&/g, "\\&")
                                      .replace(/\\r/g, "\\r")
                                      .replace(/\\t/g, "\\t")
                                      .replace(/\\b/g, "\\b")
                                      .replace(/\\f/g, "\\f");
// myEscapedJSONString is now ready to be POST'ed to the server. 

Но это довольно неприятно, не так ли? Введите всю прелесть функций в том, что они позволяют разбивать код на части и поддерживать чистоту основного потока вашего сценария без 8 цепочек .replace()вызовов. Итак, давайте поместим эту функциональность в функцию с именем escapeSpecialChars(). Давайте идти вперед и прикрепить его к prototype chainиз Stringобъекта, таким образом , мы можем назвать escapeSpecialChars()непосредственно на объекты типа String.

Вот так:

String.prototype.escapeSpecialChars = function() {
    return this.replace(/\\n/g, "\\n")
               .replace(/\\'/g, "\\'")
               .replace(/\\"/g, '\\"')
               .replace(/\\&/g, "\\&")
               .replace(/\\r/g, "\\r")
               .replace(/\\t/g, "\\t")
               .replace(/\\b/g, "\\b")
               .replace(/\\f/g, "\\f");
};

После того как мы определили эту функцию, основная часть нашего кода выглядит так просто:

var myJSONString = JSON.stringify(myJSON);
var myEscapedJSONString = myJSONString.escapeSpecialChars();
// myEscapedJSONString is now ready to be POST'ed to the server
Alex
источник
3
Спасибо, Алекс. Я должен сделать это для всех escape-символов, верно? Есть ли библиотека JS для этого?
Срикант
2
Это именно та функция, которая решила мою проблему String.prototype.escapeSpecialChars = function () {return this.replace (/ \\ / g, "\\\\"). заменить (/ \ n / g, "\\ n"). заменить (/ \ r / g, "\\ r"). заменить (/ \ t / g, "\\ t"). заменить (/ \ f / g, "\\ f"). (заменить / "/ г," \\\ ""). заменить (/ '/ г, "\\\'). заменить (/ \ & / g, "\\ &"); }
Srikant
10
Как отмечено в ответе пользователя 667073, в этом решении есть несколько ошибок. Смотрите json.org - & и ' не должно быть экранирования.
Александр Климетчек
5
Мне пришлось отказаться от голосования, так как регулярные выражения кажутся неправильными. Я пытался использовать его, но пришлось исправить регулярные выражения, удалив одну из косых черт, например: / \\ n / g должно быть / \ n / g. Для получения дополнительной информации см. «Непечатные символы» по этой ссылке - Информация RegExp
b01
1
как насчет \ себя? следует ли это также избежать?
Араш Моин
65

Согласно предложенному пользователю 667073, за исключением изменения порядка замены обратной косой черты и исправления замены кавычек

escape = function (str) {
  return str
    .replace(/[\\]/g, '\\\\')
    .replace(/[\"]/g, '\\\"')
    .replace(/[\/]/g, '\\/')
    .replace(/[\b]/g, '\\b')
    .replace(/[\f]/g, '\\f')
    .replace(/[\n]/g, '\\n')
    .replace(/[\r]/g, '\\r')
    .replace(/[\t]/g, '\\t');
};
Райан
источник
3
Вам не нужно делать все это. Только обратный слеш, перевод строки, перевод строки и две кавычки. И это отсутствует: одинарная кавычка, Line separator \u2028и Paragraph separator \u2029. Ссылка: es5.github.io/#x7.3
Ариэль
1
Хорошо, но зачем нужны квадратные скобки, а нет: escape = function (str) {return str .replace (/ \\ / g, '\\\\') .replace (/ \ "/ g, '\\\ "') .replace (/ \ // g,' \\ / ') .replace (/ \ b / g,' \\ b ') .replace (/ \ f / g,' \\ f ') .replace (/ \ n / g, '\\ n') .replace (/ \ r / g, '\\ r') .replace (/ \ t / g, '\\ t'); };
Иоганн Эчаваррия
3
идеальный. принятый ответ (выше этого) просто не работает. используя nodeJS.
Йосси Шашо
Я получаю эту ошибку:Uncaught SyntaxError: Unexpected token \ in JSON at position 2
Патросе
32

Как и вы, я просматривал несколько комментариев и публикацию, чтобы заменить специальные escape-символы в моем JSON, который содержит html-объект внутри.

Мой объект состоит в том, чтобы удалить специальные символы в объекте JSON, а также отобразить html, который находится внутри объекта json.

Вот что я сделал и надеюсь, что его очень просто использовать.

Сначала я сделал JSON.stringify мой объект json и JSON.parse результат.

Например:

JSON.parse(JSON.stringify(jsonObject));

И это решает мою проблему и сделано с использованием чистого Javascript.

Баласубрамани М
источник
4
Это определенно путь
Оз Лодригес
1
Это определенно путь!
MartianE
1
Это определенно сломается на сложных и больших объектах с stackoverflowошибкой
AaA
1
попробуйте JSON.parse(JSON.stringify($("body")))в HTML-файл с телом и несколько таблиц. $ ("body") является объектом javascript, но stringify не сможет его проанализировать.
AaA
Я проверю ваш запрос и вернусь.
Баласубрамани М
24

Боюсь сказать, что ответ, данный Алексом, мягко говоря, неверен:

  • Некоторым персонажам, которые Алекс пытается убежать, вовсе не обязательно бежать (например, & и ');
  • \ b вовсе не символ возврата, а скорее совпадение границы слова
  • Символы, необходимые для экранирования, не обрабатываются.

Эта функция

escape = function (str) {
    // TODO: escape %x75 4HEXDIG ?? chars
    return str
      .replace(/[\"]/g, '\\"')
      .replace(/[\\]/g, '\\\\')
      .replace(/[\/]/g, '\\/')
      .replace(/[\b]/g, '\\b')
      .replace(/[\f]/g, '\\f')
      .replace(/[\n]/g, '\\n')
      .replace(/[\r]/g, '\\r')
      .replace(/[\t]/g, '\\t')
    ; };

кажется, лучшее приближение.

whaefelinger
источник
5
на самом деле вы должны изменить порядок, чтобы заменить обратную косую черту перед двойными кавычками, иначе вы получите \\\\ ". Также строка кавычек должна быть .replace (/ [\"] / g, '\\\ "')
Райан
10

Небольшое обновление для одиночных кавычек

function escape (key, val) {
    if (typeof(val)!="string") return val;
    return val      
        .replace(/[\\]/g, '\\\\')
        .replace(/[\/]/g, '\\/')
        .replace(/[\b]/g, '\\b')
        .replace(/[\f]/g, '\\f')
        .replace(/[\n]/g, '\\n')
        .replace(/[\r]/g, '\\r')
        .replace(/[\t]/g, '\\t')
        .replace(/[\"]/g, '\\"')
        .replace(/\\'/g, "\\'"); 
}

var myJSONString = JSON.stringify(myJSON,escape);
Акаш Дхавале
источник
7

это старый пост но это все еще может быть полезно для тех, кто использует angular.fromJson и JSON.stringify. escape () устарела. используйте это вместо этого,

var uri_enc = encodeURIComponent(uri); //before you post the contents
var uri_dec = decodeURIComponent(uri_enc); //before you display/use the contents.

ссылка http://www.w3schools.com/jsref/jsref_decodeuricomponent.asp

Сэм
источник
stringify уже делает все возможное для вас - мне интересно, почему бы просто не использовать это? git.io/vglq7
Бен Дэвис,
5

Существует также второй параметр в JSON.stringify. Итак, более элегантным решением будет:

function escape (key, val) {
    if (typeof(val)!="string") return val;
    return val
      .replace(/[\"]/g, '\\"')
      .replace(/[\\]/g, '\\\\')
      .replace(/[\/]/g, '\\/')
      .replace(/[\b]/g, '\\b')
      .replace(/[\f]/g, '\\f')
      .replace(/[\n]/g, '\\n')
      .replace(/[\r]/g, '\\r')
      .replace(/[\t]/g, '\\t')
    ; 
}

var myJSONString = JSON.stringify(myJSON,escape);
Крунослав Джякович
источник
5

Это старый вопрос, но решение не помогло мне, так как не помогло решить все вопросы. Я наконец нашел ответ, который сделал работу здесь

Я опубликую свое комбинированное решение как с использованием escape, так и кодирования компонента uri:

// implement JSON stringify serialization
JSON.stringify = JSON.stringify || function (obj) {
    var t = typeof (obj);
    if (t != "object" || obj === null) {
        // simple data type
        if (t == "string") obj = '"'+obj+'"';
        return String(obj);
    }
    else {
        // recurse array or object
        var n, v, json = [], arr = (obj && obj.constructor == Array);
        for (n in obj) {
            v = obj[n]; t = typeof(v);
            if (t == "string") v = '"'+v+'"';
            else if (t == "object" && v !== null) v = JSON.stringify(v);
            json.push((arr ? "" : '"' + n + '":') + String(v));
        }
        var rawString = (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
       return rawString;
    }
};
function escape (key, val) {
    if (typeof(val)!="string") return val;

    var replaced = encodeURIComponent(val);
    return replaced;
}

JSON.stringifyEscaped = function(obj){
    return JSON.stringify(obj,escape);
}
Mitzi
источник
Может быть, потом удалить двойные кавычки вокруг строки? escape = (string) -> JSON.stringify(string)[1...-1]
Радек
3

Лучше использовать JSON.parse(yourUnescapedJson);

Мохит Вачхани
источник
3

Используйте json_encode (), если ваш язык сценариев на стороне сервера - PHP, json_encode() экранирует символ новой строки и другие неожиданные для вас токены (если вы не используете PHP, найдите аналогичную функцию для вашего языка сценариев)

тогда используйте $.parseJSON()в своем JavaScript, готово!

avngr
источник
Если передача данных из php в javascript в виде строки JSON, проверьте этот ответ - двойное экранирование, помогло мне передать JSON.parse и преобразовать строку json в объект. <script> windows.data_from_php = <?php echo json_encode(json_encode($arrayOrObjToJs)); ?>; var phpData = JSON.parse(windows.data_from_php); </script> php JSON.parse двойное кодирование
Владимир Вуканац
2

Я попал в ту же ситуацию во время одного из моих вызовов Ajax, когда JSONвыдает ошибку из-за новой строки в поле Textarea. Приведенное здесь решение не сработало для меня. Поэтому я использовал .escapeфункцию Javascript, и она работала нормально. Затем, чтобы получить значение JSON, я просто удалился с помощью .unescape.

Анубхав Триведи
источник
Используя вызовы Ajax, я предпочитаю использовать php-функцию newStr = addlashes (str), а затем сохранять в db. Так что мне не нужно конвертировать на стороне javascript (клиента). С этим решением вам нужно только одно место для преобразования слешей. Я очень доволен этим решением.
Марсель Энникс
2

Я использовал встроенный jQuery.serialize () для извлечения значения из текстовой области, чтобы urlencode ввода. Профессиональная часть заключается в том, что вам не нужно искать заменять каждый специальный символ самостоятельно, а я также сохраняю переводы строк и экранирование html. Чтобы сериализация работала, кажется, что поле ввода должно иметь атрибут name, но оно также добавляет тот же атрибут к экранированной строке, которую необходимо заменить. Может быть не то, что вы ищете, но это работает для меня.

var myinputfield = jQuery("#myinputfield"); 
var text = myinputfield.serialize();
text = text.replace(myinputfield.attr('name') + '=','');
Janspeed
источник
1

При использовании любой формы Ajax в Интернете, похоже, отсутствует подробная документация для формата ответов, полученных от сервера CGI. Некоторые записи здесь указывают на то, что переводы строки в возвращаемом тексте или данных JSON должны быть экранированы, чтобы предотвратить бесконечные циклы (зависания) при преобразовании JSON (возможно, созданное с помощью исключения uncaught), независимо от того, выполняется ли это автоматически с помощью jQuery или вручную с использованием системы Javascript или синтаксического анализа JSON библиотеки звонки.

В каждом случае, когда программисты публикуют эту проблему, предоставляются неадекватные решения (чаще всего заменяя \ n на \\ n на стороне отправителя), и вопрос упускается. Их неадекватность проявляется при передаче строковых значений, которые случайно встраивают управляющие управляющие последовательности, такие как пути Windows. Примером является «C: \ Chris \ Roberts.php», который содержит управляющие символы ^ c и ^ r, которые могут вызвать преобразование JSON строки {"file": "C: \ Chris \ Roberts.php"} в цикл навсегда. Одним из способов получения таких значений является намеренная попытка передачи предупреждений и сообщений об ошибках PHP с сервера на клиент, разумная идея.

По определению, Ajax использует HTTP-соединения за кулисами. Такие соединения передают данные с использованием GET и POST, оба из которых требуют кодирования отправленных данных, чтобы избежать неправильного синтаксиса, включая управляющие символы.

Это дает достаточно подсказки для построения того, что кажется решением (требуется дополнительное тестирование): использовать rawurlencode на стороне PHP (отправляющий) для кодирования данных и unescape на стороне Javascript (принимающий) для декодирования данных. В некоторых случаях вы будете применять их ко всем текстовым строкам, в других случаях вы будете применять их только к значениям внутри JSON.

Если эта идея окажется верной, можно построить простые примеры, чтобы помочь программистам на всех уровнях решить эту проблему раз и навсегда.

Дэвид Спектор
источник
0

Похоже, это действительно древний пост :-) Но, ребята, лучший способ обойти это, чтобы на 100% работать без сложного кода, это использовать обе функции кодирования / декодирования для base64. Это atob () и btoa (). Безусловно, самый простой и лучший способ, не нужно беспокоиться, если вы пропустили какие-либо символы, которые нужно экранировать.

Джордж

Giorgoc
источник
Так как я придумал то же решение. Интересно, кто-то может прояснить это решение и есть ли какие-то скрытые предостережения? Спасибо.
Махиш
0

Если ваши Googles продолжают высадить вас здесь, и ваш API выдает ошибки, если ваши двойные кавычки JSON не экранированы ( "{\"foo\": true}"), все, что вам нужно сделать, - это дважды преобразовать строкуJSON.stringify(JSON.stringify(bar))

безволия
источник
-1

Используйте encodeURIComponent () для кодирования строки.

Например. var myEscapedJSONString = encodeURIComponent (JSON.stringify (myJSON));

Вам не нужно декодировать его, так как веб-сервер автоматически делает то же самое.

Санджу Канияматтам
источник
-8

Никогда не используйте регулярные выражения (я имею в виду, как никогда). Лучший и эффективный способ:

String.prototype.escapeJSON = function() {
    var result = "";
    for (var i = 0; i < this.length; i++)
    {
        var ch = this[i];
        switch (ch)
        {
            case "\\": ch = "\\\\"; break;
            case "\'": ch = "\\'"; break;
            case "\"": ch = '\\"'; break;
            case "\&": ch = "\\&"; break;
            case "\t": ch = "\\t"; break;
            case "\n": ch = "\\n"; break;
            case "\r": ch = "\\r"; break;
            case "\b": ch = "\\b"; break;
            case "\f": ch = "\\f"; break;
            case "\v": ch = "\\v"; break;
            default: break;
        }

        result += ch;
    }

    return result;
};
Алек Деплер
источник
Вы не можете сказать: «Никогда не используйте регулярные выражения (я имею в виду, как никогда вообще)». Каждый инструмент служит своей цели.
zstate
Ваш ответ действителен, вы просто выразили его очень самоуверенно, что может создать путаницу, особенно для юниоров.
zstate
Регулярные выражения @oncode невероятно бесполезны, независимо от того, как и когда их использовать. Это приводит только к неопределенному поведению и потере времени процессора.
Алек Деплер