4

I've done some coding in RoR, and in Rails, when I return a JSON object via an API call, it returns as

{ "id" : "1", "name" : "Dan" }.

However in Python (with Flask and Flask-SQLAlchemy), when I return a JSON object via json.dumps or jsonpickle.encode it is returned as

"{ \"id\" : \"1\", \"name\": \"Dan\" }" which seems very unwieldily as it can't easily be parsed on the other end (by an iOS app in this case - Obj-C).

What am I missing here, and what should I do to return it as a JSON literal, rather than a JSON string?

This is what my code looks like:

people = models.UserRelationships.query.filter_by(user_id=user_id, active=ACTIVE_RECORD)
friends = people.filter_by(friends=YES)

json_object = jsonpickle.encode(friends.first().as_dict(), unpicklable=False, keys=True)
print(json_object)  # this prints here, i.e. { "id" : "1", "name" : "Dan" }

return json_object # this returns "{ \"id\" : \"1\", \"name\": \"Dan\" }" to the browser
4

4 回答 4

3

What is missing in your understanding here is that when you use the JSON modules in Python, you're not working with a JSON object. JSON is by definition just a string that matches a certain standard.

Lets say you have the string:

friends = '{"name": "Fred", "id": 1}'

If you want to work with this data in python, you will want to load it into a python object:

import json
friends_obj = json.loads(friends)

At this point friends_obj is a python dictionary.

If you want to convert it (or any other python dictionary or list) then this is where json.dumps comes in handy:

friends_str = json.dumps(friends_obj)
print friends_str
'{"name": "Fred", "id": 1}'

However if we attempt to "dump" the original friends string you'll see you get a different result:

dumped_str = json.dumps(friends)
print dumped_str
'"{\\"name\\": \\"Fred\\", \\"id\\": 1}"'

This is because you're basically attempting to encode an ordinary string as JSON and it is escaping the characters. I hope this helps make sense of things!

Cheers

于 2013-10-31T22:35:54.870 回答
2

Looks like you are using Django here, in which case do something like

from django.utils import simplejson as json
...
return HttpResponse(json.dumps(friends.first().as_dict()))
于 2013-10-31T22:18:53.830 回答
1

This is almost always a sign that you're double-encoding your data somewhere. For example:

>>> obj = { "id" : "1", "name" : "Dan" }
>>> j = json.dumps(obj)
>>> jj = json.dumps(j)
>>> print(obj)
{'id': '1', 'name': 'Dan'}
>>> print(j)
{"id": "1", "name": "Dan"}
>>> print(jj)
"{\"id\": \"1\", \"name\": \"Dan\"}"

Here, jj is a perfectly valid JSON string representation—but it's not a representation of obj, it's a representation of the string j, which is useless.

Normally you don't do this directly; instead, either you started with a JSON string rather than an object in the first place (e.g., you got it from a client request or from a text file), or you called some function in a library like requests or jsonpickle that implicitly calls json.dumps with an already-encoded string. But either way, it's the same problem, with the same solution: Just don't double-encode.

于 2013-10-31T22:34:20.250 回答
0

You should be using flask.jsonify, which will not only encode correctly, but also set the content-type headers accordingly.

people = models.UserRelationships.query.filter_by(user_id=user_id, active=ACTIVE_RECORD)
friends = people.filter_by(friends=YES)

return jsonify(friends.first().as_dict())
于 2013-11-03T00:03:54.547 回答