Why I can't use urlencode to encode json format data?

urlencode can encode a dict, but not a string. The output of json.dumps is a string.

Depending on what output you want, either don't encode the dict in JSON:

>>> urllib.urlencode({'title':"hello world!",'anonymous':False,'needautocategory':True})
'needautocategory=True&anonymous=False&title=hello+world%EF%BC%81'

or wrap the whole thing in a dict:

>>> urllib.urlencode({'data': json.dumps({'title':"hello world!",'anonymous':False,'needautocategory':True})})
'data=%7B%22needautocategory%22%3A+true%2C+%22anonymous%22%3A+false%2C+%22title%22%3A+%22hello+world%5Cuff01%22%7D'

or use quote_plus() instead (urlencode uses quote_plus for the keys and values):

>>> urllib.quote_plus(json.dumps({'title':"hello world!",'anonymous':False,'needautocategory':True}))
'%7B%22needautocategory%22%3A+true%2C+%22anonymous%22%3A+false%2C+%22title%22%3A+%22hello+world%5Cuff01%22%7D'

Because urllib.urlencode "converts a mapping object or a sequence of two-element tuples to a “percent-encoded” string...". Your string is neither of these.

I think you need urllib.quote or urllib.quote_plus.


json.dumps() returns a string.

urllib.urlencode() expects a query in the format of a mapping object or tuples. Note that it does not expect a string.

You're passing the first as the parameter for the second, resulting in the error.