36

First off, I will freely concede to being little more than a clumsy liberal arts guy who is completely self taught in this scripting thing. That said, I am attempting to get values from a the USGS Water Data Service using the code below:

def main(gaugeId):

    # import modules
    import urllib2, json

    # create string
    url = "http://waterservices.usgs.gov/nwis/iv/?format=json&sites=" + gaugeId + "&parameterCd=00060,00065"

    # open connection to url
    urlFile = urllib2.urlopen(url)

    # load into local JSON list
    jsonList = json.load(urlFile)

    # extract and return
    # how to get cfs, ft, and zulu time?
    return [cfs, ft, time]

Although I have found some tutorials regarding how to extract the desired values from a JSON response, most are fairly simple. The difficulty I am having is extracting from what looks like a very complicated response this service is returning. Looking through the response, I can see what I want is the value from two different sections and a time value. Hence, I can look at the response and see what I need, I just cannot, for the life of me, figure out how to get these values extracted.

martineau
  • 112,593
  • 23
  • 157
  • 280
knu2xs
  • 818
  • 2
  • 10
  • 22
  • 7
    Can you give a sample of the json and what value you need? Or a value for `gaugeId` that we can use. – Burhan Khalid Oct 08 '12 at 19:31
  • Somebody asked to see the JSON response. I apologize for not including it orginally. Rather than post the entire thing (it is rather large), just follow this link: http://waterservices.usgs.gov/nwis/iv/?format=json&sites=01646500&parameterCd=00060,00065. From what I can tell, I am looking for value>timeSeries>variable>value>value – knu2xs Oct 09 '12 at 15:36

5 Answers5

78

using json.loads will turn your data into a python dictionary.

Dictionaries values are accessed using ['key']

resp_str = {
  "name" : "ns1:timeSeriesResponseType",
  "declaredType" : "org.cuahsi.waterml.TimeSeriesResponseType",
  "scope" : "javax.xml.bind.JAXBElement$GlobalScope",
  "value" : {
    "queryInfo" : {
      "creationTime" : 1349724919000,
      "queryURL" : "http://waterservices.usgs.gov/nwis/iv/",
      "criteria" : {
        "locationParam" : "[ALL:103232434]",
        "variableParam" : "[00060, 00065]"
      },
      "note" : [ {
        "value" : "[ALL:103232434]",
        "title" : "filter:sites"
      }, {
        "value" : "[mode=LATEST, modifiedSince=null]",
        "title" : "filter:timeRange"
      }, {
        "value" : "sdas01",
        "title" : "server"
      } ]
    }
  },
  "nil" : false,
  "globalScope" : true,
  "typeSubstituted" : false
}

would translate into a python diction

resp_dict = json.loads(resp_str)

resp_dict['name'] # "ns1:timeSeriesResponseType"

resp_dict['value']['queryInfo']['creationTime'] # 1349724919000
Eric Palakovich Carr
  • 21,758
  • 8
  • 49
  • 53
dm03514
  • 52,703
  • 18
  • 104
  • 141
21

Only suggestion is to access your resp_dict via .get() for a more graceful approach that will degrade well if the data isn't as expected.

resp_dict = json.loads(resp_str)
resp_dict.get('name') # will return None if 'name' doesn't exist

You could also add some logic to test for the key if you want as well.

if 'name' in resp_dict:
    resp_dict['name']
else:
    # do something else here.
rajan
  • 139
  • 1
  • 2
  • 9
ButtersB
  • 455
  • 1
  • 7
  • 13
8

Extract single value from JSON response Python

Try this

import json
import sys

#load the data into an element
data={"test1" : "1", "test2" : "2", "test3" : "3"}

#dumps the json object into an element
json_str = json.dumps(data)

#load the json to a string
resp = json.loads(json_str)

#print the resp
print (resp)

#extract an element in the response
print (resp['test1'])
SitiSchu
  • 1,006
  • 10
  • 19
Sireesh Yarlagadda
  • 11,766
  • 3
  • 71
  • 74
3

Try this. Here, I fetch only statecode from COVID API - JSON Array.

import requests

r = requests.get('https://api.covid19india.org/data.json')

x=r.json()['statewise']

for i in x:
  print(i['statecode'])
0

Try this:

from functools import reduce
import re


def deep_get_imps(data, key: str):
    split_keys = re.split("[\\[\\]]", key)
    out_data = data
    for split_key in split_keys:
        if split_key == "":
            return out_data
        elif isinstance(out_data, dict):
            out_data = out_data.get(split_key)
        elif isinstance(out_data, list):
            try:
                sub = int(split_key)
            except ValueError:
                return None
            else:
                length = len(out_data)
                out_data = out_data[sub] if -length <= sub < length else None
        else:
            return None
    return out_data


def deep_get(dictionary, keys):
    return reduce(deep_get_imps, keys.split("."), dictionary)

Then you can use it like below:

res = {
    "status": 200,
    "info": {
        "name": "Test",
        "date": "2021-06-12"
    },
    "result": [{
        "name": "test1",
        "value": 2.5
    }, {
        "name": "test2",
        "value": 1.9
    },{
        "name": "test1",
        "value": 3.1
    }]
}

>>> deep_get(res, "info")
{'name': 'Test', 'date': '2021-06-12'}
>>> deep_get(res, "info.date")
'2021-06-12'
>>> deep_get(res, "result")
[{'name': 'test1', 'value': 2.5}, {'name': 'test2', 'value': 1.9}, {'name': 'test1', 'value': 3.1}]
>>> deep_get(res, "result[2]")
{'name': 'test1', 'value': 3.1}
>>> deep_get(res, "result[-1]")
{'name': 'test1', 'value': 3.1}
>>> deep_get(res, "result[2].name")
'test1'
azec-pdx
  • 4,541
  • 6
  • 51
  • 84
Heedo Lee
  • 31
  • 2