1

Good morning; I'm trying to pull some key values from the URL generated JSON file.

I'm able to pull the JSON from the URL without issues (line 8 is printed for reference)

def get_url():
    api_conditions_url = 'http://magicseaweed.com/api/' + API_KEY + '/forecast/?spot_id=' + PUTSBOROUGH_SPOT_ID
    print('Collecting data from - ' + api_conditions_url)
    try:
        f = urlopen(api_conditions_url)
    except:
        return []
    json_currently = f.read()
    print(json_currently)
    f.close()
    return json.loads(json_currently)

def main():
    curr_conditions = get_url()
    if ("absMinBreakingHeight" not in curr_conditions["swell"]):
        print ("Error #001 JSON call failed, check your query is correct!]\n")
        exit()
    else:
        print('it worked')

if __name__ == "__main__":
    main()

The JSON file looks like the below:


{  
      "timestamp":1564617600,
      "localTimestamp":1564617600,
      "issueTimestamp":1564617600,
      "fadedRating":0,
      "solidRating":0,
      "swell":{  
         "absMinBreakingHeight":1.3,
         "absMaxBreakingHeight":2.03,
         "probability":100,
         "unit":"ft",
         "minBreakingHeight":1,
         "maxBreakingHeight":2,
         "components":{  
            "combined":{  
               "height":3,
               "period":6,
               "direction":75.97,
               "compassDirection":"WSW"
            },
            "primary":{  
               "height":2.5,
               "period":6,
               "direction":65.06,
               "compassDirection":"WSW"
            },
            "secondary":{  
               "height":1.1,
               "period":6,
               "direction":160.71,
               "compassDirection":"NNW"
            }
         }
      },
      "wind":{  
         "speed":5,
         "direction":127,
         "compassDirection":"NW",
         "chill":60,
         "gusts":6,
         "unit":"mph"
      },
      "condition":{  
         "pressure":1017,
         "temperature":61,
         "weather":"10",
         "unitPressure":"mb",
         "unit":"f"
      },
      "charts":{  
         "swell":"https:\/\/charts-s3.msw.ms\/archive\/wave\/750\/1-1564617600-1.gif",
         "period":"https:\/\/charts-s3.msw.ms\/archive\/wave\/750\/1-1564617600-2.gif",
         "wind":"https:\/\/charts-s3.msw.ms\/archive\/gfs\/750\/1-1564617600-4.gif",
         "pressure":"https:\/\/charts-s3.msw.ms\/archive\/gfs\/750\/1-1564617600-3.gif",
         "sst":"https:\/\/charts-s3.msw.ms\/archive\/sst\/750\/1-1564617600-10.gif"
      }
   },

I receive the following error when trying to parse the JSON file -

if ("absMinBreakingHeight" not in curr_conditions["swell"]):

TypeError: list indices must be integers or slices, not str"

9
  • Looks like curr_conditions is a list and you only showed us part of it. Commented Aug 1, 2019 at 9:33
  • 3
    Is it possible that f = urlopen(api_conditions_url) in your try and except block fails and the get_url function returns an empty list? Commented Aug 1, 2019 at 9:34
  • @AlexHall - How do I change this from a list to something I can call. I used the same code to pull a different JSON file without issues. I've compared the two JSON files, and look the same. Commented Aug 1, 2019 at 9:35
  • 2
    Please share the full JSON Commented Aug 1, 2019 at 9:35
  • 1
    I think your json might be list of dicts i.e. [{}, {}] and you might need to iterate over it and check. i.e.curr_conditions[0]["swell"] Commented Aug 1, 2019 at 9:36

3 Answers 3

3

Got it. The JSON is a list of dicts (see below)
See https://magicseaweed.com/developer/forecast-api

You’ll receive a JSON array consisting of a series of data representing the forecast for specific timeframes, looking like this:

So you code should do a for loop over it.

for forecast in forecasts:
    # your logic goes here

JSON

[{
timestamp: 1366902000,
localTimestamp: 1366902000,
issueTimestamp: 1366848000,
fadedRating: 0,
solidRating: 0,
swell: {
    minBreakingHeight: 1,
    absMinBreakingHeight: 1.06,
    maxBreakingHeight: 2,
    absMaxBreakingHeight: 1.66,
    unit: "ft",
    components: {
         combined: {
         height: 1.1,
         period: 14,
         direction: 93.25,
         compassDirection: "W"
    },
    primary: {
         height: 1,
         period: 7,
         direction: 83.37,
         compassDirection: "W"
    },
    secondary: {
         height: 0.4,
         period: 9,
         direction: 92.32,
         compassDirection: "W"
    },
    tertiary: {
         height: 0.3,
         period: 13,
         direction: 94.47,
         compassDirection: "W"
     }
     }
},
wind: {
     speed: 10,
     direction: 85,
     compassDirection: "W",
     chill: 15,
     gusts: 13,
     unit: "mph"
},
condition: {
     pressure: 1020,
     temperature: 18,
     unitPressure: "mb",
     unit: "c"
},
charts: {
    swell: "http://cdn.magicseaweed.com/wave/750/1-1366902000-1.gif",
    period: "http://cdn.magicseaweed.com/wave/750/1-1366902000-2.gif",
    wind: "http://cdn.magicseaweed.com/gfs/750/1-1366902000-4.gif",
    pressure: "http://cdn.magicseaweed.com/gfs/750/1-1366902000-3.gif",
    sst: "http://cdn.magicseaweed.com/sst/750/1-1366902000-10.gif"
}
}]
Sign up to request clarification or add additional context in comments.

Comments

0

You must convert string to dict, change your main function like this.

import ast 

def main():
    curr_conditions = get_url()
    curr_conditions = ast.literal_eval(curr_conditions) # add this sentence
    if ("absMinBreakingHeight" not in curr_conditions["swell"]):
        print ("Error #001 JSON call failed, check your query is correct!]\n")
        exit()
    else:
        print('it worked')





Comments

-1

Thanks to all for their input. I tried all the methods and all were correct - The JSON was a list of dict's. Applying a "[0]" to section "" curr_conditions[0]["swell"]) "" allowed me to pull the value from the JSON.

def get_url():
    api_conditions_url = 'http://magicseaweed.com/api/' + API_KEY + '/forecast/?spot_id=' + PUTSBOROUGH_SPOT_ID
    print('Collecting data from - ' + api_conditions_url)
    try:
        f = urlopen(api_conditions_url)
    except:
        return []
    json_currently = f.read()
    print(f)
    f.close()
    return json.loads(json_currently)

def main():
    curr_conditions = get_url()
    if ("absMinBreakingHeight" not in curr_conditions[0]["swell"]):
        print ("Error #001 JSON call failed, check your query is correct!]\n")
        exit()
    else:
        print(curr_conditions[0]["swell"]["absMinBreakingHeight"])

if __name__ == "__main__":
    main()

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.