TypeError: <built-in function id> is not JSON serializable
Asked Answered
K

2

5

I'm trying to make a connection to this website "android-review.googlesource.com" through "httplib.HTTPSConnection" which actually is Gerrit (a tool for reviewing code), Gerrit API provides an interface to JSON formatted review data. I need to gather JSON data then. You can find more information about Gerrit here: https://gerritreview.googlesource.com/Documentation/rest-api.html

Let me explain a bit about source code. There is a function called "GetRequestOrCached" which saves data in a file for cache usage and another function "MakeRequest" which creates a connection to website and return the response. But error is related to the part which json.dumps is used for a request (req) which request is a dictionary.

This is the error:

TypeError: <built-in function id> is not JSON serializable

This is the code:

import socket, sys
import httplib
import pyodbc
import json
import types
import datetime
import urllib2
import os
import logging
import re, time

def GetRequestOrCached( url, method, data, filename):

  path = os.path.join("json", filename)
  if not os.path.exists(path):
    data = MakeRequest(url, method, data)
    time.sleep(1)
    data = data.replace(")]}'", "")
    f = open(path, "w")
    f.write(data)
    f.close()
    return open(path).read()

def MakeRequest(url, method, data, port=443):
  successful = False
  while not successful:
    try:
      conn = httplib.HTTPSConnection("android-review.googlesource.com", port)
      headers = {"Accept": "application/json,application/jsonrequest",
        "Content-Type": "application/json; charset=UTF-8",
        "Content-Length": len(data)}
      conn.request(method, url, data, headers)
      conn.set_debuglevel(1)
      successful = True
    except socket.error as err:
        # this means a socket timeout
      if err.errno != 10060:
        raise(err)
      else:
        print err.errno, str(err)
        print "sleep for 1 minute before retrying"
        time.sleep(60)

  resp = conn.getresponse()
  if resp.status != 200:
    raise GerritDataException("Got status code %d for request to %s" % (resp.status, url))
  return resp.read()
#-------------------------------------------------
filename = "%d-ChangeDetails.json"
url = "/gerrit_ui/rpc/ChangeDetailService"
req = {"jsonrpc" : "2.0", 
  "method": "changeDetail",
  "params": [{"id": id}],
  "id": 44
      }
data = GetRequestOrCached(url, "POST", json.dumps(req), filename)
print json.loads(data)

This line causes the error "data = GetRequestOrCached(url, "POST", json.dumps(req), filename)". I will appreciate if the one who fixes the error also check to see if the response from website is an error or a correct response.

Karyosome answered 4/7, 2014 at 21:54 Comment(1)
Sorry if this is a dumb question, but where does the variable id get its value?Leasehold
B
6

The error message says it all - you have the id function inside your req dictionary:

req = {"jsonrpc" : "2.0", 
  "method": "changeDetail",
  "params": [{"id": id}],
#                    ^- here
  "id": 44
}

Functions are not json serializable, so that's why you get the error.

On a side note - if you wanted to pass a variable instead, you've not initialized it before using it. Avoid using names of builtins as variable names (like id, int, ...) to avoid this kind of problem.

Bottle answered 4/7, 2014 at 22:0 Comment(0)
I
2

You probably forgot to assign to the variable named id before using it when assigning to req.

Because you didn't assign to it, the builtin function named id is picked up, and passed on, to be json-ized. Since it is a function, it cannot be json-ized.

If the same had happened with a name which doesn't happen to be a builtin, you would have got:

UnboundLocalError: local variable referenced before assignment
Igneous answered 4/7, 2014 at 22:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.