Как правильно разобрать JSON с simplejson?

1

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

{ "response" : [ [ { "name" : "LA_",
          "uid" : 123456
        } ],
      [ { "cid" : "1",
          "name" : "Something"
        } ],
      [ { "cid" : 1,
          "name" : "Something-else"
        } ]
    ] }

или одно из следующего:

{"error":"some-error"}

{ "response" : [ [ { "name" : "LA_",
          "uid" : 123456
        } ],
      [ { "cid" : "1",
          "name" : ""
        } ],
      [ { "cid" : 1,
          "name" : "Something-else"
        } ]
    ] }

{ "response" : [ [ { "name" : "LA_",
          "uid" : 123456
        } ] ] }

Итак, я не уверен, есть ли все дети и элементы. Будет ли достаточно сделать следующие проверки, чтобы получить Something значение:

if jsonstr.get('response'):
    jsonstr = jsonstr.get('response')[1][0]
    if jsonstr:
        name = jsonstr.get('name')
        if jsonstr: # I don't need empty value
            # save in the database

Можно ли это упростить?

Теги:
simplejson

1 ответ

2
Лучший ответ

Вам не гарантируется, что упорядочение ваших внутренних объектов будет одинаковым при каждом его анализе, поэтому индексирование не является безопасной ставкой для ссылки на индекс объекта с атрибутом name установленным на Something.

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

>>> data = {"response":[[{"uid":123456,"name":"LA_"}],[{"cid":"1","name":"Something"}],[{"cid":1,"name":"Something-else"}]]}
>>> [lst for lst in data.get('response')]
[[{'name': 'LA_', 'uid': 123456}], [{'name': 'Something', 'cid': '1'}], [{'name': 'Something-else', 'cid': 1}]]

Если вы индексируете первый элемент в каждом списке (lst[0]), вы получаете список объектов:

>>> [lst[0] for lst in data.get('response')]
[{'name': 'LA_', 'uid': 123456}, {'name': 'Something', 'cid': '1'}, {'name': 'Something-else', 'cid': 1}]

Если вы затем добавите условие if в ваше понимание списка для соответствия атрибуту name для объектов, вы получите список с одним элементом, содержащим нужный вам объект:

>>> [lst[0] for lst in data.get('response') if lst[0].get('name') == 'Something']
[{'name': 'Something', 'cid': '1'}]

И затем, индексируя первый элемент этого финального списка, вы получаете желаемый объект:

>>> [lst[0] for lst in data.get('response') if lst[0].get('name') == 'Something'][0]
{'name': 'Something', 'cid': '1'}

Итак, вы можете просто превратить это в функцию и продолжить свою жизнь:

def get_obj_by_name(data, name):
    objects = [lst[0] for lst in data.get('response', []) if lst[0].get('name') == name]
    if objects:
        return objects[0]

    return None

print get_obj_by_name(data, 'Something')
# => {'name': 'Something', 'cid': '1'}

print get_obj_by_name(data, 'Something')['name']
# => 'Something'

И он должен быть устойчивым и возвращать None если ключ response не найден:

print get_obj_by_name({"error":"some-error"}, 'Something')
# => None
  • 0
    Спасибо, @jathanism, за столь подробный ответ. На самом деле, «что-то» - это значение, которое я ищу - это может быть любое другое значение. Сторонняя сторона не предоставляет мне никакого идентификатора этого элемента, поэтому я должен полагаться на их последовательность.
  • 0
    Пожалуйста. :)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню