aghad
aghad

Reputation: 29

Python ---- TypeError: string indices must be integers

I have the below Python code

from flask import Flask, jsonify, json

app = Flask(__name__)

with open('C:/test.json', encoding="latin-1") as f:
    dataset = json.loads(f.read())

@app.route('/api/PDL/<string:dataset_identifier>', methods=['GET'])
def get_task(dataset_identifier):
    global dataset
    dataset = [dataset for dataset in dataset if dataset['identifier'] == dataset_identifier]
    if len(task) == 0:
        abort(404)
    return jsonify({'dataset': dataset})

if __name__ == '__main__':
    app.run(debug=True)

Test.json looks like this:

 {
    "dataset":  [{
                        "bureauCode":  [
                                           "016:00"
                                       ],
                        "description":  "XYZ",
                        "contactPoint":  {
                                             "fn":  "AG",
                                             "hasEmail":  "mailto:[email protected]"
                                         },
                        "distribution":  [
                                             {
                                                 "format":  "XLS",
                                                 "mediaType":  "application/vnd.ms-excel",
                                                 "downloadURL":  "https://www.example.com/xyz.xls"
                                             }
                                         ],
                        "programCode":  [
                                            "000:000"
                                        ],
                        "keyword":  [                                   "return to work",
                                    ],
                        "modified":  "2015-10-14",
                        "title":  "September 2015",
                        "publisher":  {
                                          "name":  "abc"
                                      },
                        "identifier":  US-XYZ-ABC-36,
                        "rights":  null,
                        "temporal":  null,
                        "describedBy":  null,
                        "accessLevel":  "public",
                        "spatial":  null,
                        "license":  "http://creativecommons.org/publicdomain/zero/1.0/",
                        "references":  [
                                           "http://www.example.com/example.html"
                                       ]
                    }
                ],
    "conformsTo":  "https://example.com"
}

When I pass the variable in the URL like this: http://127.0.0.1:5000/api/PDL/1403 I get the following error: TypeError: string indices must be integers

Knowing that the "identifier" field is a string and I am passing the following in the URL:

http://127.0.0.1:5000/api/PDL/"US-XYZ-ABC-36"
http://127.0.0.1:5000/api/PDL/US-XYZ-ABC-36

I keep getting the following error:

TypeError: string indices must be integers

Any idea on what am I missing here? I am new to Python!

Upvotes: 2

Views: 2391

Answers (2)

mcubik
mcubik

Reputation: 134

The problem is that you are trying to iterate the dictionary instead of the list of datasources inside it. As a consequence, you're iterating through the keys of the dictionary, which are strings. Additionaly, as it was mentioned by above, you will have problems if you use the same name for the list and the iterator variable.

This worked for me:

[ds for ds in dataset['dataset'] if ds['identifier'] == dataset_identifier]

Upvotes: 2

ShadowRanger
ShadowRanger

Reputation: 155363

The problem you have right now is that during iteration in the list comprehension, the very first iteration changes the name dataset from meaning the dict you json.loads-ed to a key of that dict (dicts iterate their keys). So when you try to look up a value in dataset with dataset['identifier'], dataset isn't the dict anymore, it's the str key of you're currently iterating.

Stop reusing the same name to mean different things.

From the JSON you posted, what you probably want is something like:

with open('C:/test.json', encoding="latin-1") as f:
    alldata = json.loads(f.read())

@app.route('/api/PDL/<string:dataset_identifier>', methods=['GET'])
def get_task(dataset_identifier):
    # Gets the list of data objects from top level object
    # Could be inlined into list comprehension, replacing dataset with alldata['dataset']
    dataset = alldata['dataset']
    # data is a single object in that list, which should have an identifier key
    # data_for_id is the list of objects passing the filter
    data_for_id = [data for data in dataset if data['identifier'] == dataset_identifier]
    if len(task) == 0:
        abort(404)
    return jsonify({'dataset': data_for_id})

Upvotes: 1

Related Questions