Правильный способ справиться с вариациями в сериализации JSON
-
05-07-2019 - |
Вопрос
У меня есть веб-сервис, который использует SimpleJSON на Python для сериализации JSON, и javascript / клиент, который использует визуализацию Google API.Когда я пытаюсь прочитать ответ JSON, используя метод запроса таблицы данных Google, я получаю ошибку "недопустимая метка".
Я заметил, что Google spreadsheet выводит JSON без кавычек вокруг ключей объекта.Я попробовал читать в JSON без кавычек, и это сработало.Мне было интересно, каков наилучший способ получить выходные данные SimpleJSON для чтения в Google datable с помощью
query = new google.visualization.Query("http://www.myuri.com/api/")
.
Я мог бы использовать регулярное выражение для удаления кавычек, но это кажется неаккуратным.Библиотеки синтаксического анализа javascript JSON, которые я пробовал, не будут читаться в синтаксисе JSON без кавычек вокруг ключей объекта.
Вот несколько хороших предысторий для чтения.:кавычки вокруг ключей объекта:
Решение
Вы уверены, что Google API ожидает JSON? По моему опыту, API-интерфейсы Google, как правило, не имеют массовых нарушений, как вы описываете, - возможно, они ожидают другого формата, который просто напоминает JSON.
<Ч>Дальнейшие осмотры показывают инструкции по извлечению данных в формате, ожидаемом Google:
Например, чтобы получить dataSourceUrl из таблицы Google, выполните следующее:
<Ол>В таблице выберите диапазон ячеек. Выберите «Вставить», а затем «Гаджет» в меню. Откройте меню гаджета, нажав на верхний правый селектор. Выберите пункт меню «Получить URL источника данных». Ол>
Я сделал это и открыл URL в моем браузере. Данные, которые он возвращал, были, конечно, не в формате JSON:
google.visualization.Query.setResponse(
{requestId:'0',status:'ok',signature:'1464883469881501252',
table:{cols: [{id:'A',label:'',type:'t',pattern:''},
{id:'B',label:'',type:'t',pattern:''}],
rows: [[{v:'a'},{v:'h'}],[{v:'b'},{v:'i'}],[{v:'c'},{v:'j'}],[{v:'d'},{v:'k'}],[{v:'e'},{v:'l'}],[{v:'f'},{v:'m'}],[{v:'g'},{v:'n'}]]}});
Похоже, что результат предназначен для непосредственного выполнения браузером. Попробуйте изменить код, чтобы сделать что-то вроде этого:
# old
return simplejson.dumps ({"requestId": 1, "status": "ok", ...})
# new
json = simplejson.dumps ({"requestId": 1, "status": "ok", ...})
return "google.visualization.Query.setResponse(%r);" % json
Другие советы
" недействительный ярлык " ошибка обычно происходит из-за слепого eval () в строке JSON, в результате чего имена свойств ошибочно принимают за метки (поскольку они имеют одинаковый синтаксис - " foo: ").
eval("{ foo: 42, bar: 43 }"); // Results in invalid label
Быстрое решение - убедиться, что в строке JSON есть круглые скобки, заключающие фигурные скобки:
eval("({ foo: 42, bar: 43 })"); // Works
Попробуйте заключить строку JSON в круглые скобки, чтобы проверить, является ли " неверная метка " ошибка исчезает.
Как оказалось :mod:json также было бы заглушать строки, заключенные в одинарные кавычки.Однако это все уладит:
Синтаксический анализ объекта JavaScript как JSON в python:
решение:
>>> from re import sub
>>> import json
>>> js = "{ a: 'a' }"
>>> json.loads(sub("'", '"', sub('\s(\w+):', r' "\1":', js)))
{u'a': u'a'}
Редактировать: (рассмотрены крайние случаи)
Итак, было поднято вопрос о том, что предлагаемое решение не справится со всеми случаями и, в частности, с чем-то вроде
например ,{фу:"предложение:прямо здесь!"} будет заменено на {"foo":"а "предложение":прямо здесь!"}
– Джейсон С. 12 апреля в 18:03
Чтобы решить эту проблему, нам просто нужно убедиться, что мы на самом деле работаем с ключом, а не просто с двоеточием в строке, поэтому мы немного разберемся с магией, чтобы намекнуть на наличие запятой (,) или фигурной скобки ({), чтобы убедиться, что у нас все правильно, вот так:
двоеточие в строке:
>>> js = "{foo: 'a sentence: right here!'}"
>>> json.loads(sub("'", '"', sub('(?<={|,)\s*(\w+):', r' "\1":', js)))
{u'foo': u'a sentence: right here!'}
Что, конечно, то же самое, что делать:
>>> js = "{foo: 'a sentence: right here!'}"
>>> json.loads(sub('(?<={|,)\s*(\w+):', r' "\1":', js).replace("'",'"'))
{u'foo': u'a sentence: right here!'}
Но затем я указал, что это не единственный недостаток, потому что как насчет кавычек:
Если нас также беспокоят экранированные кавычки, нам придется быть немного более конкретными относительно того, что представляет собой строку.Первая кавычка будет следовать либо за фигурной скобкой ({), либо за пробелом (\s), либо за двоеточием (:), в то время как последняя совпадающая кавычка будет стоять либо перед запятой(,), либо перед закрывающей фигурной скобкой(}), тогда мы можем рассматривать все, что находится между ними, как часть одной и той же строки, вот так:
дополнительные кавычки в строке:
>>> js = "{foo: 'a sentence: it\'s right here!'}"
>>> json.loads(
... sub("(?<=\s|{|:)'(.*?)'(?=,|})",
... r'"\1"',
... sub('(?<={|,)\s*(\w+):', r' "\1":', js))
... )
{u'foo': u"a sentence: it's right here!"}
Наблюдайте за этим пространством по мере выявления и решения новых крайних случаев.Можете ли вы заметить еще один?
Или, возможно, для чего-то более сложного, примера из реального мира, возвращаемого npm view
:
От:
{ name: 'chuck', description: 'Chuck Norris joke dispenser.', 'dist-tags': { latest: '0.0.3' }, versions: '0.0.3', maintainers: 'qard ', time: { '0.0.3': '2011-08-19T22:00:54.744Z' }, author: 'Stephen Belanger ', repository: { type: 'git', url: 'git://github.com/qard/chuck.git' }, version: '0.0.3', dependencies: { 'coffee-script': '>= 1.1.1' }, keywords: [ 'chuck', 'norris', 'jokes', 'funny', 'fun' ], bin: { chuck: './bin/chuck' }, main: 'index', engines: { node: '>= 0.4.1 < 0.5.0' }, devDependencies: {}, dist: { shasum: '3af700056794400218f99b7da1170a4343f355ec', tarball: 'http://registry.npmjs.org/chuck/-/chuck-0.0.3.tgz' }, scripts: {}, directories: {}, optionalDependencies: {} }
Для:
{u'author': u'Stephen Belanger ', u'bin': {u'chuck': u'./bin/chuck'}, u'dependencies': {u'coffee-script': u'>= 1.1.1'}, u'description': u'Chuck Norris joke dispenser.', u'devDependencies': {}, u'directories': {}, u'dist': {u'shasum': u'3af700056794400218f99b7da1170a4343f355ec', u'tarball': u'http://registry.npmjs.org/chuck/-/chuck-0.0.3.tgz'}, u'dist-tags': {u'latest': u'0.0.3'}, u'engines': {u'node': u'>= 0.4.1 < 0.5.0'}, u'keywords': [u'chuck', u'norris', u'jokes', u'funny', u'fun'], u'main': u'index', u'maintainers': u'qard ', u'name': u'chuck', u'optionalDependencies': {}, u'repository': {u'type': u'git', u'url': u'git://github.com/qard/chuck.git'}, u'scripts': {}, u'time': {u'0.0.3': u'2011-08-19T22:00:54.744Z'}, u'version': u'0.0.3', u'versions': u'0.0.3'}
У меня работает =)
Нджой!