Reputation: 96806
How does one return a dict
like object through protoRPC
?
I tried using the FieldList
to no avail. I only see the following field definitions:
'IntegerField',
'FloatField',
'BooleanField',
'BytesField',
'StringField',
'MessageField',
'EnumField',
Upvotes: 3
Views: 2356
Reputation: 471
It's possible to create a custom JsonField
like this :
In [1]: class JsonField(messages.StringField):
type = dict
You can then use it as any other field :
In [2]: class MyMessage(messages.Message):
data = JsonField(1)
In [3]: m = MyMessage(data={"foo": "bar"})
In [4]: m.data
Out [4]: {'foo': 'bar'}
Upvotes: 2
Reputation: 3570
A bit involved, but I have a recipe for something quite close to a dict implementation for protorpc
: https://gist.github.com/linuxluser/32d4a9c36ca0b8715ad4
It is restricted to using string-only keys and simple (not nested) values. But if your data fits in that category, this solution should work well.
The idea has 2 parts:
MultiField
that can hold an arbitrary value type.MapField
that stores key-value pairs in a list of MultiField
types.You use it like so:
import messages
import mapfield
class MyMessage(messages.Message):
some_dict = mapfield.MapField(1)
my_message = MyMessage(some_dict={"foo": 7, "bar": False, "baz": 9.2, "qux": "nog"})
It's only a start. Probably could be better. Improvements are welcomed. :)
Upvotes: 0
Reputation: 10163
There are two scenarios:
1) Your dict
has a well-defined schema: This is the best use case for ProtoRPC and if possible you should try to fit it into a schema. In this case, you would use a MessageField
with some Message
class that matches the schema in your dictionary.
For example, instead of
{'amount': 31, 'type': 'fish', mine: False}
you could define
from protorpc import messages
class MyCatch(messages.Message):
amount = messages.IntegerField(1)
type = messages.StringField(2)
mine = messages.BooleanField(3)
and then use this message definition in a field via
messages.MessageField(MyCatch, index, ...)
2) Your dict
does not have a well-defined schema: In this case you can use json
to dump your dictionary to a string and request ensure_ascii=True
to make sure the return type is a bytes (str
) object. Then you can just use a BytesField
.
For example:
import json
class MyMessage(messages.Message):
some_dict = messages.BytesField(1)
my_dict = {'amount': 31, 'type': 'fish', mine: False}
message = MyMessage(some_dict=json.dumps(my_dict, ensure_ascii=True))
The use of ensure_ascii
is optional as True
is the default, but this may change depending on your environment.
Instead you could use pickle
to serialize your dictionary. The method pickle.dumps
always outputs ASCII/binary, so by swapping out json.dumps
for pickle.dumps
and dropping the ensure_ascii=True
, you'd have the same outcome.
Upvotes: 8
Reputation: 168
For the first option in the approved answer, we can add a parameter repeated=True, so we'll have a list of json as the answer. I checked about it at https://developers.google.com/appengine/docs/python/tools/protorpc/overview?hl=en#Defining_the_Response_Message
Upvotes: 1