Foundations of Python Network Programming

(WallPaper) #1

Chapter 18 ■ rpC


342


Self-Documenting Data

You have just seen that both XML-RPC and JSON-RPC appear to support a data structure very much like a Python
dictionary, but with an annoying limitation. In XML-RPC, the data structure is called a struct, whereas JSON calls
it an object. To the Python programmer, however, it looks like a dictionary, and your first reaction will probably be
annoyance that its keys cannot be integers, floats, or tuples.
Let’s look at a concrete example. Imagine that you have a dictionary of physical element symbols indexed by their
atomic number:


{1: 'H', 2: 'He', 3: 'Li', 4: 'Be', 5: 'B', 6: 'C', 7: 'N', 8: 'O'}


If you need to transmit this dictionary over an RPC mechanism, your first instinct might be to change the numbers
to strings so that the dictionary can pass as a struct or object. It turns out that, in most cases, this instinct is wrong.
Simply put, the struct and object RPC data structures are not designed to pair keys with values in containers of
an arbitrary size. Instead, they are designed to associate a small set of predefined attribute names with the attribute
values that they happen to carry for some particular object. If you try to use a struct to pair random keys and values,
you might inadvertently make your service very difficult to use for people unfortunate enough to be using statically
typed programming languages.
Instead, you should think of dictionaries being sent across RPCs as being like Python objects, which typically
each have a small collection of attribute names that are well known to your code. In the same way, the dictionaries
you send across RPC should associate a small number of predefined keys with their related values.
All of this means that the dictionary presented previously should actually be serialized as a list of explicitly
labeled values if it is going to be used by a general-purpose RPC mechanism:


[{'number': 1, 'symbol': 'H'},
{'number': 2, 'symbol': 'He'},
{'number': 3, 'symbol': 'Li'},
{'number': 4, 'symbol': 'Be'},
{'number': 5, 'symbol': 'B'},
{'number': 6, 'symbol': 'C'},
{'number': 7, 'symbol': 'N'},
{'number': 8, 'symbol': 'O'}]


Note that the preceding examples show the Python dictionary as you would pass it into your RPC call, not the way
it would be represented on the wire.
The key difference in this approach (besides the fact that this dictionary is appallingly longer) is that the
earlier data structure was meaningless unless you knew ahead of time what the keys and values meant. It relied on
convention to give the data meaning. But here you are including names with the data, which makes it self-descriptive:
someone looking at these data on the wire or in a program has a higher chance of guessing what they represent.
This is how both XML-RPC and JSON-RPC expect you to use their key-value types, and this is where the names
struct and object came from. They are, respectively, the C-language and JavaScript terms for an entity that holds
named attributes. Again, this makes them much closer to being like Python objects than Python dictionaries.
If you have a Python dictionary like the one being discussed here, you can turn it into an RPC-appropriate data
structure and then change it back with code like this:





elements = {1: 'H', 2: 'He'}
t = [{'number': key, 'symbol': value} for key, value in elements.items()]
t
[{'symbol': 'H', 'number': 1}, {'symbol': 'He', 'number': 2}]
{obj['number']: obj['symbol']) for obj in t}
{1: 'H', 2: 'He'}




Free download pdf