Преобразование str в dict в python

Я получил это из вывода процесса, используя subprocess.Popen() :

    { about: 'RRDtool xport JSON output',
  meta: {
    start: 1401778440,
    step: 60,
    end: 1401778440,
    legend: [
      'rta_MIN',
      'rta_MAX',
      'rta_AVERAGE'
          ]
     },
  data: [
    [ null, null, null ],
    [ null, null, null ],
    [ null, null, null ],
    [ null, null, null ],
    [ null, null, null ],
    [ null, null, null  ]
  ]
}

Мне кажется, это недопустимый json. Я использовал ast.literal_eval() и json.loads(), но безуспешно. Может ли кто-нибудь помочь мне в правильном направлении? Заранее спасибо.


person dotslash    schedule 03.06.2014    source источник
comment
Если вы не можете заставить процесс создавать строгий JSON, попробуйте более простой синтаксический анализатор.   -  person user2357112 supports Monica    schedule 03.06.2014
comment
Это действительно недопустимый JSON; имена ключей нужно заключать в кавычки. Всегда ли JSON форматируется с таким большим количеством пробелов?   -  person Martijn Pieters    schedule 03.06.2014
comment
@MartijnPieters: Да, имена ключей действительно должны быть в кавычках. Я также не уверен в количестве пробелов.   -  person dotslash    schedule 03.06.2014
comment
@Shark: мы можем либо попытаться восстановить JSON, либо вам придется использовать demjson, чтобы загрузить это.   -  person Martijn Pieters    schedule 03.06.2014
comment
@Shark: я спрашиваю о пробелах, потому что вы могли бы переформатировать JSON для работы в сообщении здесь.   -  person Martijn Pieters    schedule 03.06.2014
comment
@MartijnPieters: Нет, я не переформатировал json, я просто скопировал вывод из subprocess.Popen().communicate()   -  person dotslash    schedule 03.06.2014
comment
@MartijnPieters: Мне действительно нужно использовать здесь demjson? Нет ли способа восстановить вышеуказанный json?   -  person dotslash    schedule 03.06.2014
comment
Просто двойные кавычки для ключей и строковых значений.   -  person salmanwahed    schedule 03.06.2014
comment
@Shark: есть, но с оговорками.   -  person Martijn Pieters    schedule 03.06.2014
comment
@salmanwahed: проблема в том, что это делается автоматически, что не нарушает формат JSON.   -  person Martijn Pieters    schedule 03.06.2014
comment
ОП хотел направление. Не код, я думаю.   -  person salmanwahed    schedule 03.06.2014


Ответы (2)


Действительно, старые версии rddtool экспортируют ECMA-скрипт, а не JSON. Согласно этому отчету об ошибках Debian, обновление 1.4.8 должно дать вам правильный JSON. Также см. проект CHANGELOG:

Вывод JSON xport теперь фактически компилируется с json, поскольку его ключи теперь правильно цитируются.

Если вы не можете обновиться, у вас есть два варианта; либо попытайтесь переформатировать, чтобы применить цитирование идентификаторов ключа объекта, либо используйте более мягкий синтаксический анализатор, который анализирует нотацию объекта ECMA-script.

Последнее можно сделать с помощью внешней demjson библиотеки:

>>> import demjson
>>> demjson.decode('''\
... { about: 'RRDtool xport JSON output',
...   meta: {
...     start: 1401778440,
...     step: 60,
...     end: 1401778440,
...     legend: [
...       'rta_MIN',
...       'rta_MAX',
...       'rta_AVERAGE'
...           ]
...      },
...   data: [
...     [ null, null, null ],
...     [ null, null, null ],
...     [ null, null, null ],
...     [ null, null, null ],
...     [ null, null, null ],
...     [ null, null, null  ]
...   ]
... }''')
{u'about': u'RRDtool xport JSON output', u'meta': {u'start': 1401778440, u'step': 60, u'end': 1401778440, u'legend': [u'rta_MIN', u'rta_MAX', u'rta_AVERAGE']}, u'data': [[None, None, None], [None, None, None], [None, None, None], [None, None, None], [None, None, None], [None, None, None]]}

Восстановление можно выполнить с помощью регулярного выражения; Я собираюсь предположить, что все идентификаторы находятся на новой строке или сразу после открывающей фигурной скобки {. Одинарные кавычки в списке придется заменить на двойные; это будет работать только в том случае, если в значениях нет встроенных одинарных кавычек:

import re
import json

yourtext = re.sub(r'(?:^|(?<={))\s*(\w+)(?=:)', r' "\1"', yourtext, flags=re.M)
yourtext = re.sub(r"'", r'"', yourtext)
data = json.loads(yourtext)
person Martijn Pieters    schedule 03.06.2014
comment
Есть ли преимущество использования demjson перед yaml? Bcz оба дают мне правильный результат. - person dotslash; 03.06.2014
comment
@Shark: YAML утверждает, что является надмножеством JSON, где этот синтаксис работает и для YAML. demjson явно допускает используемый здесь синтаксис, так как видит его как ECMAScript. Возможно, существует какой-то синтаксис, создаваемый RDDTool, который ни один из инструментов не анализирует, но я инстинктивно использую здесь demjson. - person Martijn Pieters; 03.06.2014
comment
@Shark Одно из возможных преимуществ заключается в том, что ваш вывод явно утверждает, что это JSON. Он случайно является только допустимым YAML, поэтому менее вероятно, что мягкий анализатор JSON столкнется с ним в какой-то момент в будущем. - person Zero Piraeus; 03.06.2014

Это действительно недопустимый JSON. Однако это допустимый YAML, поэтому сторонний PyYAML:

>>> import yaml
>>> yaml.load(text)
{
    'about': 'RRDtool xport JSON output',
    'meta': {
        'start': 1401778440,
        'step': 60,
        'end': 1401778440,
        'legend': [
            'rta_MIN',
            'rta_MAX',
            'rta_AVERAGE'
        ]
    },
    'data': [
        [None, None, None],
        [None, None, None],
        [None, None, None],
        [None, None, None],
        [None, None, None],
        [None, None, None]
    ]
}
person Zero Piraeus    schedule 03.06.2014