JSON.stringify без кавычек на свойствах?

98

Я использую службу, которая использует неправильный формат JSON (без двойных кавычек вокруг свойств). Так что мне нужно отправить

{ name: "John Smith" } вместо того { "name": "John Smith" }

Этот формат нельзя изменить, так как это не моя услуга.

Кто-нибудь знает о маршрутизации строкового типа для форматирования объекта JavaScript, как указано выше?

нефрит
источник

Ответы:

118

Это простое решение для регулярных выражений в большинстве случаев позволяет убрать кавычки с имен свойств JSON:

const object = { name: 'John Smith' };
const json = JSON.stringify(object);  // {"name":"John Smith"}
console.log(json);
const unquoted = json.replace(/"([^"]+)":/g, '$1:');
console.log(unquoted);  // {name:"John Smith"}

Крайний случай:

var json = '{ "name": "J\\":ohn Smith" }'
json.replace(/\\"/g,"\uFFFF");  // U+ FFFF
json = json.replace(/"([^"]+)":/g, '$1:').replace(/\uFFFF/g, '\\\"');
// '{ name: "J\":ohn Smith" }'

Особая благодарность Робу В. за его исправление.

Ограничения

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

function stringify(obj_from_json) {
    if (typeof obj_from_json !== "object" || Array.isArray(obj_from_json)){
        // not an object, stringify using native function
        return JSON.stringify(obj_from_json);
    }
    // Implements recursive object serialization according to JSON spec
    // but without quotes around the keys.
    let props = Object
        .keys(obj_from_json)
        .map(key => `${key}:${stringify(obj_from_json[key])}`)
        .join(",");
    return `{${props}}`;
}

Пример: https://jsfiddle.net/DerekL/mssybp3k/

Дерек 朕 會 功夫
источник
3
-1 тоже не я, но вы должны внимательно прочитать вопрос. OP необходимо кодировать объект в (сломанный) json, а не анализировать / оценивать его.
Salman A
7
@Derek Этот метод не является надежным . Например, возьмите этот ввод: {"foo":"e\":bar"}(действительный JSON) становится {foo:e:bar"}(...)!
Rob W
1
@Derek /\\\"/можно упростить до /\\"/. Не забудьте добавить глобальный флаг /\\"/g, иначе он будет разбит на несколько строк \". Что касается случайного символа, никогда не используйте буквальный U + FFFF, если редактор задыхается, а escape-последовательность. Регулярное выражение для возврата станет /\uFFFF/g.
Rob W
2
@Derek 朕 會 功夫 ваше регулярное выражение /\"([^(\")"]+)\":/gможно упростить /"([^"]+)":/g, см. Regex101.com/r/qnz0ld/2
tanguy_k
1
@endriu В этом случае просто добавьте дополнительную проверку на нулевые значения.
Derek 朕 會 功夫
18

Похоже, это простой метод Object toString, который вы ищете.

В Node.js это решается с помощью объекта util и вызова util.inspect (yourObject). Это даст вам все, что вы хотите. перейдите по этой ссылке, чтобы узнать о дополнительных возможностях, включая глубину применения метода. http://nodejs.org/api/util.html#util_util_inspect_object_options

Итак, то, что вы ищете, - это инспектор объектов, а не конвертер JSON. Формат JSON указывает, что все свойства должны быть заключены в двойные кавычки. Следовательно, не будет конвертеров JSON, которые бы делали то, что вы хотите, поскольку это просто не формат JSON. Технические характеристики здесь: https://developer.mozilla.org/en-US/docs/Using_native_JSON

Возражение против строки или проверки - это то, что вам нужно, в зависимости от языка вашего сервера.

фино
источник
1
Спасибо тебе большое! Это именно то, что я искал. Я использую json для передачи данных через ws-сервер в свою игру, и, хотите верьте, хотите нет, отсутствие необходимости иметь дело с лишними кавычками вокруг имен свойств позволяет сэкономить огромное количество данных! Чтобы уточнить, .toSource()отлично работает и в nodejs, но не работает с объектами в массивах. utilИнспектировать работы для массивов и объектов в массивах , которые замечательно, любят его.
NiCk Newman
3
util.inspect()просто отлично поработал для меня при написании объекта в запросе Neo4j, чтобы установить сразу несколько параметров.
agm1984
1
Из ссылки nodejs:> Метод util.inspect () возвращает строковое представление объекта, предназначенного для отладки. Вывод util.inspect может измениться в любой момент, и на него нельзя полагаться программно.
Питер Роулен
5

Вы можете посмотреть исходный код парсера, созданного тем, кто определил формат JSON . Ищите вызовы функций: они заключают значение в кавычки. Ключи указаны в строках 326 и 338 .json2.js quote

Не включайте библиотеку после модификации. Вместо этого возьмите только соответствующую stringifyчасть ( ) или, по крайней мере, замените JSONчем-то другим, например. FAKEJSON.

Например, объект, FAKEJSONкоторый определен только stringify: http://jsfiddle.net/PYudw/

Роб В
источник
Зачем вам нужна дополнительная библиотека, если вы можете сделать это на чистом JavaScript?
Derek 朕 會 功夫
Это хорошая идея. Я бы разделил репо, удалил кавычки и переименовал объект JSON во что-нибудь шутливое, например FAILJSON, чтобы было ясно, что вы не работаете с фактическим объектом JSON или фактическим JSON.
RichardTowers
@Derek Библиотеку не следует включать целиком. Только принять JSON.stringifyучастие, а цитаты убрать. Поскольку библиотека создается тем, кто определил JSON , мы можем быть уверены, что результатом будет очень правильный JSON.
Rob W
Похоже, это лучший подход.
Derek 朕 會 功夫
Да, согласен с Дереком. Хотя его заменитель работает нормально, я чувствую себя более уверенно с кодом Кроуфорда, никакого неуважения к Дереку Лолу. .toSource()работает хорошо, но не включает, если ваш объект находится в массиве, который является обломом (и я нахожусь на узле, поэтому совместимость браузера не является проблемой: P), поэтому я также буду использовать этот метод, спасибо @RobW, ссылка jsfiddle кажется застрять на странице загрузки :(
NiCk Newman
4

Попробуйте использовать сервив с JSONP, я думаю, они его предлагают при использовании этого формата.

Или отправьте им подробный отчет об ошибке, включая хорошую аргументацию, почему они должны соответствовать стандарту. Любое другое решение, кроме устранения проблемы с источником, не является реальным решением.

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

var obj = JSON.parse(str.replace(/(\{|,)\s*(.+?)\s*:/g, '$1 "$2":'));

Или вы пытаетесь настроить существующий парсер javascript JSON (например, этот ), если хотите более синтаксический анализ.

Берги
источник
3

Нашел хороший пакет NPM для этого:

https://www.npmjs.com/package/stringify-object

const stringify = require('stringify-object')

let prettyOutput = stringify(json);

Работает неплохо.

user1543276
источник
1
Эта библиотека не рекурсивна.
Corysimmons
2

Ваш унаследованный синтаксис должен быть легко съеден YAML, который является надмножеством JSON.

Попробуйте синтаксический анализатор и дампер JavaScript YAML: http://nodeca.github.com/js-yaml/

user1649339
источник
2

@Derek 朕 會 功夫 Спасибо за то, что поделились этим методом, я хочу поделиться своим кодом, который также поддерживает строковое преобразование массива объектов.

export const stringifyObjectWithNoQuotesOnKeys = (obj_from_json) => {
    // In case of an array we'll stringify all objects.
    if (Array.isArray(obj_from_json)) {
        return `[${
                    obj_from_json
                        .map(obj => `${stringifyObjectWithNoQuotesOnKeys(obj)}`)
                        .join(",")
                }]` ;
    }
    // not an object, stringify using native function
    if(typeof obj_from_json !== "object" || obj_from_json instanceof Date || obj_from_json === null){
        return JSON.stringify(obj_from_json);
    }
    // Implements recursive object serialization according to JSON spec
    // but without quotes around the keys.
    return `{${
            Object
                .keys(obj_from_json)
                .map(key => `${key}:${stringifyObjectWithNoQuotesOnKeys(obj_from_json[key])}`)
                .join(",")
            }}`;
};
Адель Бачен
источник
1
Вы также должны использовать JSON.stringifyinstanceof Date. Также верните, 'null'если значение obj_from_jsonnull.
Дальний Дмитрий
1
Я просто исправил вопросы, поднятые @FarDmitry, изменив второе условие if, чтобы оно выглядело следующим образом:if(typeof obj_from_json !== "object" || obj_from_json instanceof Date || obj_from_json === null)
Брунно Водола Мартинс
2

Использовать JSON5.stringify

JSON5 является надстройкой JSON , который позволяет ES5 синтаксис, в том числе некотируемых ключей свойств. Эталонная реализация JSON5 ( json5пакет npm ) предоставляет JSON5объект, который имеет те же методы с теми же аргументами и семантикой, что и встроенный JSONобъект.

Весьма вероятно, что служба, которую вы используете, использует эту библиотеку.

Иниго
источник
1

В CSVJSON JSON Beautifier есть возможность добавлять кавычки на ключи. Если вам нужен только код, вы можете скопировать его из репозитория GitHub. Я модифицировал JSON2 Дугласа Крокфорда, чтобы добавить его поддержку.

Мартин Драпо
источник
Просто нажал на csvjson.com/json_beautifier и получил другую страницу, чем я ожидал ... hacked by AnoaGhost
RedctedProfile
Очищено сейчас. Приносим извинения за неудобства.
Мартин Драпо