/lib/galaxy/util/json.py

https://bitbucket.org/cistrome/cistrome-harvard/ · Python · 110 lines · 99 code · 10 blank · 1 comment · 37 complexity · bae755ce203fb3d4a07394bfc63571fe MD5 · raw file

  1. from __future__ import absolute_import
  2. __all__ = [ "to_json_string", "from_json_string", "json_fix", "validate_jsonrpc_request", "validate_jsonrpc_response", "jsonrpc_request", "jsonrpc_response" ]
  3. import json
  4. import logging
  5. import random
  6. import socket
  7. import string
  8. to_json_string = json.dumps
  9. from_json_string = json.loads
  10. log = logging.getLogger( __name__ )
  11. def json_fix( val ):
  12. if isinstance( val, list ):
  13. return [ json_fix( v ) for v in val ]
  14. elif isinstance( val, dict ):
  15. return dict( [ ( json_fix( k ), json_fix( v ) ) for ( k, v ) in val.iteritems() ] )
  16. elif isinstance( val, unicode ):
  17. return val.encode( "utf8" )
  18. else:
  19. return val
  20. # Methods for handling JSON-RPC
  21. def validate_jsonrpc_request( request, regular_methods, notification_methods ):
  22. try:
  23. request = from_json_string( request )
  24. except Exception, e:
  25. return False, request, jsonrpc_response( id = None, error = dict( code = -32700, message = 'Parse error', data = str( e ) ) )
  26. try:
  27. assert 'jsonrpc' in request, \
  28. 'This server requires JSON-RPC 2.0 and no "jsonrpc" member was sent with the Request object as per the JSON-RPC 2.0 Specification.'
  29. assert request['jsonrpc'] == '2.0', \
  30. 'Requested JSON-RPC version "%s" != required version "2.0".' % request['jsonrpc']
  31. assert 'method' in request, 'No "method" member was sent with the Request object'
  32. except AssertionError, e:
  33. return False, request, jsonrpc_response( request = request, error = dict( code = -32600, message = 'Invalid Request', data = str( e ) ) )
  34. try:
  35. assert request['method'] in ( regular_methods + notification_methods )
  36. except AssertionError, e:
  37. return False, request, jsonrpc_response( request = request,
  38. error = dict( code = -32601,
  39. message = 'Method not found',
  40. data = 'Valid methods are: %s' % ', '.join( regular_methods + notification_methods ) ) )
  41. try:
  42. if request['method'] in regular_methods:
  43. assert 'id' in request, 'No "id" member was sent with the Request object and the requested method "%s" is not a notification method' % request['method']
  44. except AssertionError, e:
  45. return False, request, jsonrpc_response( request = request, error = dict( code = -32600, message = 'Invalid Request', data = str( e ) ) )
  46. return True, request, None
  47. def validate_jsonrpc_response( response, id=None ):
  48. try:
  49. response = from_json_string( response )
  50. except Exception, e:
  51. log.error( 'Response was not valid JSON: %s' % str( e ) )
  52. log.debug( 'Response was: %s' % response )
  53. return False, response
  54. try:
  55. assert 'jsonrpc' in response, \
  56. 'This server requires JSON-RPC 2.0 and no "jsonrpc" member was sent with the Response object as per the JSON-RPC 2.0 Specification.'
  57. assert ( 'result' in response or 'error' in response ), \
  58. 'Neither of "result" or "error" members were sent with the Response object.'
  59. if 'error' in response:
  60. assert int( response['error']['code'] ), \
  61. 'The "code" member of the "error" object in the Response is missing or not an integer.'
  62. assert 'message' in response, \
  63. 'The "message" member of the "error" object in the Response is missing.'
  64. except Exception, e:
  65. log.error( 'Response was not valid JSON-RPC: %s' % str( e ) )
  66. log.debug( 'Response was: %s' % response )
  67. return False, response
  68. if id is not None:
  69. try:
  70. assert 'id' in response and response['id'] == id
  71. except Exception, e:
  72. log.error( 'The response id "%s" does not match the request id "%s"' % ( response['id'], id ) )
  73. return False, response
  74. return True, response
  75. def jsonrpc_request( method, params=None, id=None, jsonrpc='2.0' ):
  76. if method is None:
  77. log.error( 'jsonrpc_request(): "method" parameter cannot be None' )
  78. return None
  79. request = dict( jsonrpc = jsonrpc, method = method )
  80. if params:
  81. request['params'] = params
  82. if id is not None and id is True:
  83. request['id'] = ''.join( [ random.choice( string.hexdigits ) for i in range( 16 ) ] )
  84. elif id is not None:
  85. request['id'] = id
  86. return request
  87. def jsonrpc_response( request=None, id=None, result=None, error=None, jsonrpc='2.0' ):
  88. if result:
  89. rval = dict( jsonrpc = jsonrpc, result = result )
  90. elif error:
  91. rval = dict( jsonrpc = jsonrpc, error = error )
  92. else:
  93. msg = 'jsonrpc_response() called with out a "result" or "error" parameter'
  94. log.error( msg )
  95. rval = dict( jsonrpc = jsonrpc, error = msg )
  96. if id is not None:
  97. rval['id'] = id
  98. elif request is not None and 'id' in request:
  99. rval['id'] = request['id']
  100. return rval