]> git.evergreen-ils.org Git - OpenSRF.git/blob - src/python/osrf/json.py
da3dad4a6843946a2a3c9acb187b7fb1d207456d
[OpenSRF.git] / src / python / osrf / json.py
1 import simplejson, types 
2 from osrf.net_obj import NetworkObject, parse_net_object
3 from osrf.const import OSRF_JSON_PAYLOAD_KEY, OSRF_JSON_CLASS_KEY
4
5 class NetworkEncoder(simplejson.JSONEncoder):
6     def default(self, obj):
7
8         if isinstance(obj, NetworkObject):
9             reg = obj.get_registry()
10             data = obj.get_data()
11
12             # re-encode the object as an array if necessary
13             if reg.protocol == 'array':
14                 objarray = []
15                 for key in reg.keys:
16                     objarray.append(data.get(key)) 
17                 data = objarray
18
19             return { 
20                 OSRF_JSON_CLASS_KEY: reg.hint,
21                 OSRF_JSON_PAYLOAD_KEY: self.default(data)
22             }   
23         return obj
24
25
26 def to_json(obj):
27     """Turns a python object into a wrapped JSON object"""
28     return simplejson.dumps(obj, cls=NetworkEncoder)
29
30
31 def to_object(json):
32     """Turns a JSON string into python objects"""
33     obj = simplejson.loads(json)
34     return parse_net_object(obj)
35
36 def parse_json_raw(json):
37     """Parses JSON the old fashioned way."""
38     return simplejson.loads(json)
39
40 def to_json_raw(obj):
41     """Stringifies an object as JSON with no additional logic."""
42     return simplejson.dumps(obj)
43
44 def __tabs(depth):
45     space = ''
46     while range(depth):
47         space += '   '
48     return space
49
50 def debug_net_object(obj, depth=1):
51     """Returns a debug string for a given object.
52
53     If it's an NetworkObject and has registered keys, key/value pairs
54     are returned.  Otherwise formatted JSON is returned"""
55
56     debug_str = ''
57     if isinstance(obj, NetworkObject):
58         reg = obj.get_registry()
59         keys = list(reg.keys) # clone it, so sorting won't break the original
60         keys.sort()
61
62         for k in keys:
63
64             key = k
65             while len(key) < 24: key += '.' # pad the names to make the values line up somewhat
66             val = getattr(obj, k)()
67
68             subobj = val and not (isinstance(val, unicode) or \
69                 isinstance(val, int) or isinstance(val, float) or isinstance(val, long))
70
71             debug_str += __tabs(depth) + key + ' = '
72
73             if subobj:
74                 debug_str += '\n'
75                 val = debug_net_object(val, depth+1)
76
77             debug_str += str(val)
78
79             if not subobj: debug_str += '\n'
80
81     else:
82         debug_str = pprint(to_json(obj))
83     return debug_str
84
85 def pprint(json):
86     """JSON pretty-printer"""
87     r = ''
88     t = 0
89     instring = False
90     inescape = False
91     done = False
92     eatws = False
93
94     for c in json:
95
96         if eatws: # simpljson adds a pesky space after array and object items
97             if c == ' ': 
98                 continue
99
100         eatws = False
101         done = False
102         if (c == '{' or c == '[') and not instring:
103             t += 1
104             r += c + '\n' + __tabs(t)
105             done = True
106
107         if (c == '}' or c == ']') and not instring:
108             t -= 1
109             r += '\n' + __tabs(t) + c
110             done = True
111
112         if c == ',' and not instring:
113             r += c + '\n' + __tabs(t)
114             done = True
115             eatws = True
116
117         if c == ':' and not instring:
118             eatws = True
119
120         if c == '"' and not inescape:
121             instring = not instring
122
123         if inescape: 
124             inescape = False
125
126         if c == '\\':
127             inescape = True
128
129         if not done:
130             r += c
131
132     return r