Правильный способ справиться с вариациями в сериализации JSON

StackOverflow https://stackoverflow.com/questions/176749

Вопрос

У меня есть веб-сервис, который использует 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 без кавычек вокруг ключей объекта.

Вот несколько хороших предысторий для чтения.:кавычки вокруг ключей объекта:

http://simonwillison.net/2006/Oct/11/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'}

    У меня работает =)

    Нджой!

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top