Як уникнути рядка JSON, що містить символи нового рядка за допомогою JavaScript?


166

Я повинен сформувати рядок JSON, у якому значення має новий рядковий символ. Цього потрібно уникнути, а потім опублікувати за допомогою AJAX-дзвінка. Чи може хтось запропонувати спосіб вийти з рядка за допомогою JavaScript. Я не використовую jQuery.


1
Я намагався вийти з нового символу рядка \ n в \\ n. Це прекрасно працює. Але я шукаю будь-яку бібліотеку JS, яка може зробити це для всіх символів втечі.
Шрікант

1
Чому потрібно уникати нових ліній в межах JSON? Як розшифровуються ці значення при їх використанні, оскільки відповідним рішенням є використання відповідної функції кодування.
zzzzBov

Я витратив 6 годин на пробування всіляких речей з тоннами варіацій, щоб виявити крихітну додаткову косу рису, змусив би це працювати як магія, а речі, які я думав, важко зайняли, як 5 хвилин ... те, що я думав, було дано стало неможливим. .omg
Мухаммед Умер

1
Коли ви використовуєте Ajax-дзвінки з використанням сервера php-db-збереження на стороні сервера, просто використовуйте php-функцію addlashes () для його перетворення. Завдяки цьому рішенню у вас є лише одне місце для конвертації та його більш чисте, ніж лінії заміни javascript.
Марсель Еннікс

Дивіться відповідну відповідь та рішення на веб-сайті 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

3
Спасибі Алекс. Я повинен це зробити для всіх персонажів втечі, чи не так? Чи є якась бібліотека JS для цього?
Шрікант

2
Саме ця функція вирішила мою проблему String.prototype.escapeSpecialChars = function () {return this.replace (/ \\ / g, "\\\\"). замінити (/ \ n / g, "\\ n"). замінити (/ \ r / g, "\\ r"). замінити (/ \ t / g, "\\ t"). замінити (/ \ f / g, "\\ f"). замінити (/ "/ g," \\\ ""). замінити (/ '/ g, "\\\'"). замінити (/ \ & / g, "\\ &"); }
Шрікант

10
Як зазначається у відповіді користувача667073, в цьому рішенні є кілька помилок. Дивіться json.org - & і " не можна уникати .
Олександр Климечек

5
Мені довелося це проголосувати, оскільки регулярні вислови здаються неправильними. Я намагався ним скористатися, але довелося виправляти регулярні вирази, видаляючи одну з косої риси, наприклад: / \\ n / g має бути / \ n / g. Дивіться "Персонажі, що не
друкуються

1
як щодо \ себе? чи слід також уникати цього?
arash moeen

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, '\\\ "') .замінити (/ \ // g,' \\ / ') .замінити (/ \ 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
Pathros

32

Як і ви, я розглядав декілька коментарів і публікацій, щоб замінити спеціальні символи евакуації в моєму JSON, який містить html-об’єкт всередині цього.

Моя мета полягає в тому, щоб видалити спеціальні символи в об'єкті JSON, а також надати HTML, який знаходиться всередині об'єкта json.

Ось що я зробив і сподіваюся, що його дуже просто у використанні.

Спершу я зробив JSON.stringify мій об’єкт json і JSON.парати результат.

Наприклад:

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

І це вирішує мою проблему і робиться за допомогою чистого Javascript.


4
Це, безумовно, шлях
Оз Лодрігес

1
Це, безумовно, шлях!
MartianE

1
Це, безумовно, зламається на складних і великих об'єктах з stackoverflowпомилкою
AaA

1
спробуйте JSON.parse(JSON.stringify($("body")))у HTML-файлі з тілом та кількома таблицями. $ ("body") - це об'єкт javascript, але під час редагування не вдасться його проаналізувати.
AaA

Я перевірю ваш запит і повернусь.
Баласубрамані M

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')
    ; };

видається кращим наближенням.


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.

ref http://www.w3schools.com/jsref/jsref_decodeuricomponent.asp


Настройте вже, що для вас все можливе - мені цікаво, чому б просто не використати це? 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);
}

Можливо, видаліть також подвійні лапки навколо рядка? escape = (string) -> JSON.stringify(string)[1...-1]
Радек


3

Використовуйте json_encode (), якщо язиком сценарію на вашому сервері є PHP, json_encode()уникає нового рядка та інших несподіваних маркерів для вас (якщо не використовується PHP, шукайте подібну функцію для вашої мови сценаріїв)

потім використовуйте $.parseJSON()у своєму JavaScript, зробили!


Якщо передача даних з 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 подвійний кодування
Vladimir Vukanac

2

У мене трапилася така ж ситуація в одному з моїх дзвінків у "Аякс", де JSONбуло помилки через нову лінію в полі "Текстарея". Наведене тут рішення не працювало для мене. Тому я використав .escapeфункцію Javascript, і вона працювала чудово. Потім, щоб отримати значення з JSON, я просто не визначив, використовуючи .unescape.


Використовуючи дзвінки Ajax, я вважаю за краще використовувати php-функцію newStr = addlashes (str), а потім зберегти в db. Тож мені не доведеться конвертувати на стороні javascript- (client). За допомогою цього рішення вам потрібно лише одне місце для перетворення косої риски. Я дуже задоволений цим рішенням.
Марсель Еннікс

2

Я використовував вбудований в jQuery.serialize () для отримання значення з textarea для urlencode введення. Профільна частина полягає в тому, що вам не доведеться шукати заміни кожного спеціального символу самостійно, і я також зберігаю нові рядки та уникає html. Щоб серіалізація працювала, здається, що в полі введення потрібно мати атрибут імені, але він також додає такий же атрибут до ряду, що уникнув, який потрібно замінити. Можливо, не те, що ви шукаєте, але це працює для мене.

var myinputfield = jQuery("#myinputfield"); 
var text = myinputfield.serialize();
text = text.replace(myinputfield.attr('name') + '=','');

1

При використанні будь-якої форми Ajax детальна документація щодо формату відповідей, отриманих від сервера CGI, здається, в Інтернеті бракує. Деякі записи тут зазначають, що слід уникати нових рядків у повернених текстах або json даних для запобігання нескінченних циклів (зависань) при перетворенні JSON (можливо, створених шляхом викидання невиконаного винятку), будь то зроблено автоматично jQuery або вручну за допомогою системи Javascript або бібліотеки JSON розбору дзвінки.

У кожному випадку, коли програмісти ставлять цю проблему, представлені неадекватні рішення (найчастіше замінюючи \ n на \\ n на стороні, що надсилає), і питання залишається. Їх неадекватність виявляється при передачі рядкових значень, які випадково вбудовують керуючі послідовності аварійних змін, наприклад, імена шляхів Windows. Приклад - "C: \ Chris \ Roberts.php", який містить контрольні символи ^ c і ^ r, що може викликати перетворення JSON рядка {"файл": "C: \ Chris \ Roberts.php"} в петля назавжди. Один із способів генерування таких значень - це навмисна спроба передачі PHP повідомлень про попередження та помилки від сервера до клієнта, розумна ідея.

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

Це дає достатньо підказки для побудови того, що, здається, є рішенням (для цього потрібне додаткове тестування): використовувати rawurlencode на PHP (відсилаючій) стороні для кодування даних, а не розгорнути на стороні Javascript (отримання) для декодування даних. У деяких випадках ви застосовуватимете їх до цілих текстових рядків, в інших випадках ви застосовуватимете їх лише до значень усередині JSON.

Якщо ця ідея виявиться правильною, можна створити прості приклади, щоб допомогти програмістам на всіх рівнях вирішити цю проблему раз і назавжди.


0

Схоже, це справді давня публікація :-) Але, хлопці, найкращий спосіб вирішити це для мене, на 100%, щоб він працював без складного коду, - це використовувати обидві функції кодування / декодування для base64. Це атоб () та бтоа (). На сьогоднішній день найпростіший і найкращий спосіб, не потрібно турбуватися, якщо ви пропустили будь-які символи, на яких втекли.

Джордж


Оскільки я придумав таке ж рішення. Цікаво, чи хтось міг би уточнити це рішення, і чи є деякі приховані застереження. Дякую.
махіш

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 регулярні вирази неймовірно марні, незалежно від того, як і коли ними користуватися. Це призводить лише до невизначеної поведінки та витрачання часу на процесор.
Алек Деплер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.