442 if sys.version_info < (2, 6): |
442 if sys.version_info < (2, 6): |
443 import simplejson as json |
443 import simplejson as json |
444 else: |
444 else: |
445 import json |
445 import json |
446 except ImportError: |
446 except ImportError: |
447 json_dumps = None |
447 json_dumps = JSString = None |
448 |
448 |
449 else: |
449 else: |
450 from logilab.common.date import ustrftime |
450 from logilab.common.date import ustrftime |
451 |
451 |
452 class CubicWebJsonEncoder(json.JSONEncoder): |
452 class CubicWebJsonEncoder(json.JSONEncoder): |
476 |
476 |
477 def json_dumps(value): |
477 def json_dumps(value): |
478 return json.dumps(value, cls=CubicWebJsonEncoder) |
478 return json.dumps(value, cls=CubicWebJsonEncoder) |
479 |
479 |
480 |
480 |
|
481 class JSString(str): |
|
482 """use this string sub class in values given to :func:`js_dumps` to |
|
483 insert raw javascript chain in some JSON string |
|
484 """ |
|
485 |
|
486 def _dict2js(d, predictable=False): |
|
487 res = [key + ': ' + js_dumps(val, predictable) |
|
488 for key, val in d.iteritems()] |
|
489 return '{%s}' % ', '.join(res) |
|
490 |
|
491 def _list2js(l, predictable=False): |
|
492 return '[%s]' % ', '.join([js_dumps(val, predictable) for val in l]) |
|
493 |
|
494 def js_dumps(something, predictable=False): |
|
495 """similar as :func:`json_dumps`, except values which are instances of |
|
496 :class:`JSString` are expected to be valid javascript and will be output |
|
497 as is |
|
498 |
|
499 >>> js_dumps({'hop': JSString('$.hop'), 'bar': None}, predictable=True) |
|
500 '{bar: null, hop: $.hop}' |
|
501 >>> js_dumps({'hop': '$.hop'}) |
|
502 '{hop: "$.hop"}' |
|
503 >>> js_dumps({'hip': {'hop': JSString('momo')}}) |
|
504 '{hip: {hop: momo}}' |
|
505 """ |
|
506 if isinstance(something, dict): |
|
507 return _dict2js(something, predictable) |
|
508 if isinstance(something, list): |
|
509 return _list2js(something, predictable) |
|
510 if isinstance(something, JSString): |
|
511 return something |
|
512 return json_dumps(something) |
|
513 |
|
514 |
481 @deprecated('[3.7] merge_dicts is deprecated') |
515 @deprecated('[3.7] merge_dicts is deprecated') |
482 def merge_dicts(dict1, dict2): |
516 def merge_dicts(dict1, dict2): |
483 """update a copy of `dict1` with `dict2`""" |
517 """update a copy of `dict1` with `dict2`""" |
484 dict1 = dict(dict1) |
518 dict1 = dict(dict1) |
485 dict1.update(dict2) |
519 dict1.update(dict2) |