Package Products :: Package ZenUtils :: Module jsonutils
[hide private]
[frames] | no frames]

Source Code for Module Products.ZenUtils.jsonutils

  1  ########################################################################### 
  2  # 
  3  # This program is part of Zenoss Core, an open source monitoring platform. 
  4  # Copyright (C) 2007, Zenoss Inc. 
  5  # 
  6  # This program is free software; you can redistribute it and/or modify it 
  7  # under the terms of the GNU General Public License version 2 as published by 
  8  # the Free Software Foundation. 
  9  # 
 10  # For complete information please visit: http://www.zenoss.com/oss/ 
 11  # 
 12  ########################################################################### 
 13   
 14  import json as _json 
 15  import re 
 16   
17 -def _recursiveCaster(ob):
18 if isinstance(ob, dict): 19 result = {} 20 for k, v in ob.iteritems(): 21 result[str(k)] = _recursiveCaster(v) 22 return result 23 elif isinstance(ob, list): 24 return [_recursiveCaster(x) for x in ob] 25 elif isinstance(ob, unicode): 26 return str(ob) 27 else: 28 return ob
29 30
31 -class StringifyingDecoder(_json.JSONDecoder):
32 """ 33 Casts all unicode objects as strings. This is necessary until Zope is less 34 stupid. 35 """
36 - def decode(self, s):
37 result = super(StringifyingDecoder, self).decode(s) 38 return _recursiveCaster(result)
39
40 -class JavaScript(object):
41 """A simple class that represents a JavaScript literal that should not be JSON encoded."""
42 - def __init__(self, value):
43 self.value = value
44
45 - def __str__(self):
46 return self.value
47
48 -class JavaScriptRegex(JavaScript):
49 """A simple class that represents a JavaScript Regex literal that should not be JSON encoded."""
50 - def __str__(self):
51 return '/' + self.value + '/'
52
53 -class JavaScriptEncoder(_json.JSONEncoder):
54 """A JavaScript encoder based on JSON. It encodes like normal JSON except it passes JavaScript objects un-encoded.""" 55 56 _js_start = '__js_start__' 57 _js_end = '__js_end__' 58 _js_re = re.compile(r'\["%s", (.*?), "%s"\]' % (_js_start, _js_end)) 59
60 - def default(self, obj):
61 if isinstance(obj, JavaScript): 62 return [self._js_start, str(obj), self._js_end] 63 else: 64 return _json.JSONEncoder.default(self, obj)
65
66 - def _js_clean(self, jsonstr):
67 # This re replace is not ideal but at least the dirtyness of it is encapsulated in these classes 68 # instead of plain str manipulation being done in the wild. 69 def fix(matchobj): 70 return _json.loads(matchobj.group(1))
71 72 return self._js_re.sub(fix, jsonstr)
73
74 - def encode(self, obj):
75 return self._js_clean(_json.JSONEncoder.encode(self, obj))
76
77 -def json(value, **kw):
78 """ 79 Serialize C{value} into a JSON string. 80 81 If C{value} is callable, a decorated version of C{value} that serializes its 82 return value will be returned. 83 84 >>> value = (dict(a=1L), u"123", 123) 85 >>> print json(value) 86 [{"a": 1}, "123", 123] 87 >>> @json 88 ... def f(): 89 ... return value 90 ... 91 >>> print f() 92 [{"a": 1}, "123", 123] 93 94 @param value: An object to be serialized 95 @type value: dict, list, tuple, str, etc. or callable 96 @return: The JSON representation of C{value} or a decorated function 97 @rtype: str, func 98 """ 99 if callable(value): 100 # Decorate the given callable 101 def inner(*args, **kwargs): 102 return _json.dumps(value(*args, **kwargs))
103 # Well-behaved decorators look like the decorated function 104 inner.__name__ = value.__name__ 105 inner.__dict__.update(value.__dict__) 106 inner.__doc__ = value.__doc__ 107 return inner 108 else: 109 # Simply serialize the value passed 110 return _json.dumps(value, **kw) 111
112 -def javascript(data):
113 """A JavaScript encoder based on JSON. It encodes like normal JSON except it passes JavaScript objects un-encoded.""" 114 return json(data, cls=JavaScriptEncoder)
115
116 -def unjson(value, **kw):
117 """ 118 Create the Python object represented by the JSON string C{value}. 119 120 >>> jsonstr = '[{"a": 1}, "123", 123]' 121 >>> print unjson(jsonstr) 122 [{'a': 1}, '123', 123] 123 124 @param value: A JSON string 125 @type value: str 126 @return: The object represented by C{value} 127 """ 128 if 'cls' not in kw: 129 kw['cls'] = StringifyingDecoder 130 return _json.loads(value, **kw)
131