Python Forum

Full Version: Object of type set is not JSON serializable
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi

I've a new problem with json / python.

My json is:
Output:
{ "domaine": { "name": { "service": ["service1", "service2"], "threshold": ["100", "200"] }, ...
On my python script, I'm trying to make a request post to my icinga configuration for monitoring.

#!/usr/bin/env python3
..
with open('/tmp/config.json') as json_file1:
            data1 = json.load(json_file1)
            for domaine, value in data1.items():
                    for name, value2 in value.items():
                            service = data1[domaine][name]['service']
                            threshold = data1[domaine][name]['threshold']

                            try:
                                url = "https://localhost:5665/v1/objects/hosts/"
                                request_url = url+hostname
                                headers = {
                                    'Accept': 'application/json',
                                    'X-HTTP-Method-Override': 'PUT'
                                }
                                data = {
                                    "templates": service,
                                    "attrs": {
                                                "address":"BLABLA",
                                                "zone":"BLIBLI",
                                                "vars": { threshold }
                                    }
                                }
                                r = requests.post(request_url,
                                    headers=headers,
                                    verify=False,
                                    auth=('admin', 'XXXXXXXXXXXXXXXXXX'),
                                data=json.dumps(data))
Result is:
Output:
"vars": { threshold } TypeError: unhashable type: 'list'
If I change
Output:
threshold = data1[domaine][name]['threshold'] to: threshold = tuple(data1[domaine][name]['threshold'])
My result is:
Output:
TypeError: Object of type set is not JSON serializable
I'm trying to change key, format, ... but i'm blocked with this point...

Thanks for help
{ threshold } is a set with one element. if you pass list to set - it doesn't work because list is mutable, thus not hashable and cannot be element in a set. If you change it to tuple, the set works, but it's not seriazable, as the second error says (i.e. there is no respective type in json).
why you would like a set? what is required as per specifications? I think you misread your specs.

As a side note - fix your indentation and also, don't use spaces after/before braces/brackets i.e. {threshold}
I'm not sure about me for this point ...

In fact if I do my request with curl it works:
Output:
curl -vv -k -X PUT -u "admin:${PASSWORD_API_ADMIN}" -H 'Accept: application/json' -H 'Content-Type: application/json' -L "https://localhost:5665/v1/objects/hosts/hostname", -d "{\"templates\": [\"service1\",\"service2\"], \"attrs\": { \"address\": \"BLABLA\", \"zone\": \"BLIBLI\", \"vars\": {\"threshold1\":100, \"threshlod2\":200} } }"| python3.7 -m json.tool
So perhaps my json format is not good?
I'm a little lost with this json format

Output:
{ "domaine": { "name": { "service": ["service1", "service2"], "threshold": ["threshold1: 100", "threshold2: 200"] }, ...

Seems good.

I've changed my json config with:
Output:
"threshold": {"threshold1": "100", "threshold2": "200"}
and my python code sith:
Output:
"vars": threshold
and it works now
in curls you have a dict, not set
so
#!/usr/bin/env python3
..
with open('/tmp/config.json') as json_file1:
    data1 = json.load(json_file1)
    for domaine, value in data1.items():
        for name, value2 in value.items():
            service = data1[domaine][name]['service']
            threshold1, threshold2 = data1[domaine][name]['threshold'] # unpack the list
            try:
                url = "https://localhost:5665/v1/objects/hosts/"
                request_url = url+hostname
                headers = {
                    'Accept': 'application/json',
                    'X-HTTP-Method-Override': 'PUT'
                }
                data = {
                    "templates": service,
                    "attrs": {
                                "address":"BLABLA",
                                "zone":"BLIBLI",
                                "vars": {'threshold1':threshold1, 'threshold2':threshold2}
                    }
                }
                r = requests.post(request_url,
                    headers=headers,
                    verify=False,
                    auth=('admin', 'XXXXXXXXXXXXXXXXXX'),
                        data=json.dumps(data))
note that in curl threshold1 and threshold2 are integers, you will read them as str, so you may need to explicitly convert them
yeah, that's also possibility, if you can change the input json
Tanks for help! Have a good day!