Я повторяю сложный объект json, загружаемый как словарь в python. Ниже приведен пример json-файла. Прокомментированные данные.Простой способ перебросить сложный словарь в python?
{
"name":"ns1:timeSeriesResponseType",
"nil":false,
"value":{
"queryInfo":{ },
"timeSeries":[
{
"variable":{ },
"values":[
{
"qualifier":[ ],
"censorCode":[ ],
"value":[
{
"codedVocabularyTerm":null,
"censorCode":null,
"offsetTypeID":null,
"accuracyStdDev":null,
"timeOffset":null,
"qualifiers":[
"P", # data of interest
"Ice" # data of interest
],
"qualityControlLevelCode":null,
"sampleID":null,
"dateTimeAccuracyCd":null,
"methodCode":null,
"codedVocabulary":null,
"sourceID":null,
"oid":null,
"dateTimeUTC":null,
"offsetValue":null,
"metadataTime":null,
"labSampleCode":null,
"methodID":null,
"value":"-999999",
"dateTime":"2015-02-24T03:30:00.000-05:00",
"offsetTypeCode":null,
"sourceCode":null
},
{
"codedVocabularyTerm":null,
"censorCode":null,
"offsetTypeID":null,
"accuracyStdDev":null,
"timeOffset":null,
"qualifiers":[ ],
"qualityControlLevelCode":null,
"sampleID":null,
"dateTimeAccuracyCd":null,
"methodCode":null,
"codedVocabulary":null,
"sourceID":null,
"oid":null,
"dateTimeUTC":null,
"offsetValue":null,
"metadataTime":null,
"labSampleCode":null,
"methodID":null,
"value":"-999999", # data of interest
"dateTime":"2015-02-24T04:00:00.000-05:00", # data of interest
"offsetTypeCode":null,
"sourceCode":null
}
],
"sample":[ ],
"source":[ ],
"offset":[ ],
"units":null,
"qualityControlLevel":[ ],
"method":[ ]
}
],
"sourceInfo":{ },
"name":"USGS:03193000:00060:00011"
},
{ }, # more data need is stored in here
{ }, # more data need is stored in here
{ } # more data need is stored in here
]
},
"declaredType":"org.cuahsi.waterml.TimeSeriesResponseType",
"scope":"javax.xml.bind.JAXBElement$GlobalScope",
"globalScope":true,
"typeSubstituted":false
}
И вот мой код для пошаговых/Перебора словаря, чтобы добраться до данных Я хочу и хранить его в более просто отформатированный словаре:
# Setting up blank variables to store results
outputDict = {}
outputList = []
dateTimeList = []
valueList = []
qualifiersList = [[]]
for key in result["value"]["timeSeries"]:
for key2 in key:
if key2 == "values":
for key3 in key.get(key2):
for key4 in key3:
if key4 == "value":
for key5 in key3.get(key4):
for key6 in key5:
if key6 == "value":
valueList.append(key5.get(key6))
if key6 == "dateTime":
dateTimeList.append(key5.get(key6))
#print key.get("name")
#outputDict[key.get("name")]["dateTime"] = dateTimeList
#outputDict[key.get("name")]["values"] = valueList
if key2 == "name":
outputList.append(key.get(key2))
outputDict[key.get(key2)]={"dateTime":None, "values":None, "qualifiers":None}
outputDict[key.get("name")]["dateTime"] = dateTimeList
outputDict[key.get("name")]["values"] = valueList
del dateTimeList[:]
del valueList[:]
Мой вопрос заключается в следующем - существо несколько нового для python, может ли кто-нибудь указать на очевидную неэффективность моего кода? Я могу рассчитывать на json-файл, который не меняет структуру в течение нескольких месяцев - возможно, лет - и поэтому я считаю, что мое первоначальное использование для ключа в результате ["value"] ["timeSeries"]: - это хорошо, но Я не уверен, что многие, многие из циклов не нужны или неэффективны. Есть ли простой способ поиска и возврата пар ключ: значение из такого иерархического словаря со списками словарей внутри списков словарей?
EDIT:
На основе решения представленного @Alex Мартелла, здесь новая, более эффективная, отделанную версию коды:
# Building the output dictionary
for key in result["value"]["timeSeries"]:
if "values" in key:
for key2 in key.get("values"):
if "value" in key2:
for key3 in key2.get("value"):
if "value" in key3:
valueList.append(key3.get("value"))
if "dateTime" in key3:
dateTimeList.append(key3.get("dateTime"))
if "qualifiers" in key3:
qualifiersList.append(key3.get("qualifiers"))
if "name" in key:
outputList.append(key.get("name"))
outputDict[key.get("name")]={"dateTime":None, "values":None, "qualifiers":None}
outputDict[key.get("name")]["dateTime"] = dateTimeList[:] # passing the items in the list rather
outputDict[key.get("name")]["values"] = valueList[:] # than a reference to the list so the delete works
outputDict[key.get("name")]["qualifiers"] = qualifiersList[:] # than a reference to the list so the delete works
del dateTimeList[:]
del valueList[:]
del qualifiersList[:]
Работает так же, удален 4 строку код. Более быстрое время работы. Ницца.
EDIT:
На основе решения, предложенного @ двухбитовая Alchemist, это работает так:
# Building the output dictionary
for key in result["value"]["timeSeries"]:
print key
for value in key["values"][0]["value"]:
# qualifiers is a list containing ["P", "Ice"]
qualifiersList.append(value['qualifiers'])
valueList.append(value['value'])
dateTimeList.append(value['dateTime'])
if "name" in key:
outputList.append(key.get("name"))
outputDict[key.get("name")]={"dateTime":None, "values":None, "qualifiers":None}
outputDict[key.get("name")]["dateTime"] = dateTimeList[:] # passing the items in the list rather
outputDict[key.get("name")]["values"] = valueList[:] # than a reference to the list so the delete works
outputDict[key.get("name")]["qualifiers"] = qualifiersList[:] # than a reference to the list so the delete works
del dateTimeList[:]
del valueList[:]
del qualifiersList[:]
Единственная проблема, которую я вижу, что я никогда не полностью уверен, что первое место в списке ["values"] - это то, что я хочу. И я теряю проверки, предоставленные операторами if, проверки, которые должны гарантировать, что ошибки не будут введены, если значения возвращаются из ошибочных запросов.
EDIT:
try:
# requests.get returns a "file-like" object
# in this case it is a JSON object because of the settings in the query
response = requests.get(url=query)
# if-else ladder that only performs the parsing of the returned JSON object
# when the HTTP status code indicates a successful query execution
if(response.status_code == 200):
# parsing the
result = response.json()
# Setting up blank variables to store results
outputDict = {}
outputList = []
dateTimeList = []
valueList = []
qualifiersList = []
# Building the output dictionary
for key in result["value"]["timeSeries"]:
print key
for value in key["values"][0]["value"]:
# qualifiers is a list containing ["P", "Ice"]
qualifiersList.append(value['qualifiers'])
valueList.append(value['value'])
dateTimeList.append(value['dateTime'])
# OLD CODE
# if "values" in key:
# for key2 in key.get("values"):
# if "value" in key2:
# for key3 in key2.get("value"):
# if "value" in key3:
# valueList.append(key3.get("value"))
# if "dateTime" in key3:
# dateTimeList.append(key3.get("dateTime"))
# if "qualifiers" in key3:
# qualifiersList.append(key3.get("qualifiers"))
if "name" in key:
outputList.append(key.get("name"))
outputDict[key.get("name")]={"dateTime":None, "values":None, "qualifiers":None}
outputDict[key.get("name")]["dateTime"] = dateTimeList[:] # passing the items in the list rather
outputDict[key.get("name")]["values"] = valueList[:] # than a reference to the list so the delete works
outputDict[key.get("name")]["qualifiers"] = qualifiersList[:] # than a reference to the list so the delete works
del dateTimeList[:]
del valueList[:]
del qualifiersList[:]
# Tracking how long it took to process the data
elapsed = time.time() - now
print "Runtime: " + str(elapsed)
out = {"Status": 'ok', "Results": [[{"myResult": outputDict}]]}
elif(response.status_code == 400):
raise Exception("Bad Request, "+ datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
elif(response.status_code== 403):
raise Exception("Access Forbidden, "+ datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
elif(response.status_code == 404):
raise Exception("Gage location(s) not Found, "+ datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
elif(response.status_code == 500):
raise Exception("Internal Server Error, "+ datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
elif(response.status_code == 503):
raise Exception("Service Unavailable, "+ datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
else:
raise Exception("Unknown Response, "+ datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
except:
out = {"Status": 'Error', "Message": str(sys.exc_info()[1])}
print out
Думаю, вам просто нужно получить к нему доступ, не так ли? Что-то вроде 'dct ['value'] ['timeSeries'] [0] ['values'] [0] ['value'] [0] ['qualifiers']' if 'dct' - ваша структура json. Это может быть не совсем правильно, потому что, да, эта вещь чрезвычайно сложна! –
Итак, это сработает, если я знаю, сколько ответов на мой запрос может быть. Но в любой момент времени может быть от одного до десятка ответов, и я точно не знаю, сколько ответов, и поэтому я не знаю, сколько я должен разместить (или перебрать) в вашем решении. Если бы я всегда знал общее количество ответов, ваше предложение будет работать. Но я не уверен, может ли это иначе. – traggatmot
Какую часть этой структуры вы называете «ответом», что существует переменное число? –