Разберите только один уровень json

У меня есть следующая строка:

'{
    "key1": "val1",
    "key2": ["a","b", 3],
    "key3": {"foo": 27, "bar": [1, 2, 3]}
}'

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

Для данной строки она должна вернуть следующий словарь:

{
    "key1": "val1",
    "key2": "['a','b', 3]",
    "key3": "{'foo': 27, 'bar': [1, 2, 3]}"
}

Есть ли быстрый способ сделать это? Без разбора всей строки в json и преобразования всех значений обратно в строки.

Ответ 1

Вряд ли ответ, но я вижу только две возможности:

  • Загрузите полный JSON и сбросьте значения, которые вы исключили в свой вопрос
  • Измените контент, обернув значения в кавычках, чтобы загрузка JSON выдавала строковые значения

Честно говоря, я думаю, что нет такого понятия, как "критический JSON-анализ производительности", это просто звучит неправильно, поэтому я бы пошел с первым вариантом.

Ответ 2

Я думаю, вы можете решить это с помощью регулярного выражения, оно работает для меня:

import re
pattern = re.compile('"([a-zA-Z0-9]+)"\s*:\s*(".*"|\[.*\]|\{.*\})')    
dict(re.findall(pattern, json_string))

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

[EDIT]

Да, это быстрее. Я попробовал скрипты ниже, а версия регулярного выражения - в 5 раз быстрее.

с использованием модуля json:

import json

val='''
{
    "key1": "val1",
    "key2": ["a","b", 3],
    "key3": {"foo": 27, "bar": [1, 2, 3]}
}
'''

for n in range(100000):
    dict((k,json.dumps(v)) for k,v in json.loads(val).items())

с помощью regex:

import re

val='''{
    "key1": "val1",
    "key2": ["a","b", 3],
    "key3": {"foo": 27, "bar": [1, 2, 3]}
}'''

pattern = re.compile('"([a-zA-Z0-9]+)"\s*:\s*(".*"|\[.*\]|\{.*\})')    
for n in range(100000):
    dict(re.findall(pattern, val))

Ответ 3

Я не сейчас, если это действительно то, что вам нужно, но попробуйте

>>> import json
>>> val = """
... {
... "key1": "val1",
... "key2": ["a","b", 3],
... "key3": {"foo": 27, "bar": [1, 2, 3]}
... }
... """
>>> dict((k,json.dumps(v)) for k,v in json.loads(val).items())
{u'key3': '{"foo": 27, "bar": [1, 2, 3]}', u'key2': '["a", "b", 3]', u'key1': '"val1"'}

Это немного сложно, потому что вы загружаете полный объект JSON, а не просто возвращаете значения в словаре.