blob: 17417027a0aea72534242c7c21f3769b7596630d [file] [log] [blame]
Roger Meier85fb6de2012-11-02 00:05:42 +00001#
2# Licensed to the Apache Software Foundation (ASF) under one
3# or more contributor license agreements. See the NOTICE file
4# distributed with this work for additional information
5# regarding copyright ownership. The ASF licenses this file
6# to you under the Apache License, Version 2.0 (the
7# "License"); you may not use this file except in compliance
8# with the License. You may obtain a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing,
13# software distributed under the License is distributed on an
14# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15# KIND, either express or implied. See the License for the
16# specific language governing permissions and limitations
17# under the License.
18#
19
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090020from .TProtocol import (TType, TProtocolBase, TProtocolException,
James E. King IIIe44f6a92019-02-07 17:11:21 -050021 TProtocolFactory, checkIntegerLimits)
Roger Meier0895dfe2012-12-26 22:09:55 +010022import base64
Roger Meier0895dfe2012-12-26 22:09:55 +010023import math
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +090024import sys
25
26from ..compat import str_to_binary
27
Roger Meier85fb6de2012-11-02 00:05:42 +000028
Roger Meier0895dfe2012-12-26 22:09:55 +010029__all__ = ['TJSONProtocol',
30 'TJSONProtocolFactory',
31 'TSimpleJSONProtocol',
32 'TSimpleJSONProtocolFactory']
Roger Meier85fb6de2012-11-02 00:05:42 +000033
34VERSION = 1
35
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +090036COMMA = b','
37COLON = b':'
38LBRACE = b'{'
39RBRACE = b'}'
40LBRACKET = b'['
41RBRACKET = b']'
42QUOTE = b'"'
43BACKSLASH = b'\\'
44ZERO = b'0'
Roger Meier85fb6de2012-11-02 00:05:42 +000045
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +090046ESCSEQ0 = ord('\\')
47ESCSEQ1 = ord('u')
48ESCAPE_CHAR_VALS = {
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090049 '"': '\\"',
50 '\\': '\\\\',
51 '\b': '\\b',
52 '\f': '\\f',
53 '\n': '\\n',
54 '\r': '\\r',
55 '\t': '\\t',
56 # '/': '\\/',
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +090057}
58ESCAPE_CHARS = {
59 b'"': '"',
60 b'\\': '\\',
61 b'b': '\b',
62 b'f': '\f',
63 b'n': '\n',
64 b'r': '\r',
65 b't': '\t',
66 b'/': '/',
67}
68NUMERIC_CHAR = b'+-.0123456789Ee'
Roger Meier85fb6de2012-11-02 00:05:42 +000069
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090070CTYPES = {
71 TType.BOOL: 'tf',
72 TType.BYTE: 'i8',
73 TType.I16: 'i16',
74 TType.I32: 'i32',
75 TType.I64: 'i64',
76 TType.DOUBLE: 'dbl',
77 TType.STRING: 'str',
78 TType.STRUCT: 'rec',
79 TType.LIST: 'lst',
80 TType.SET: 'set',
81 TType.MAP: 'map',
82}
Roger Meier85fb6de2012-11-02 00:05:42 +000083
84JTYPES = {}
85for key in CTYPES.keys():
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090086 JTYPES[CTYPES[key]] = key
Roger Meier85fb6de2012-11-02 00:05:42 +000087
88
Roger Meierad8154a2012-12-18 21:02:16 +010089class JSONBaseContext(object):
Roger Meier85fb6de2012-11-02 00:05:42 +000090
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090091 def __init__(self, protocol):
92 self.protocol = protocol
93 self.first = True
Roger Meier85fb6de2012-11-02 00:05:42 +000094
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090095 def doIO(self, function):
96 pass
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +090097
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090098 def write(self):
99 pass
Roger Meier85fb6de2012-11-02 00:05:42 +0000100
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900101 def read(self):
102 pass
Roger Meier85fb6de2012-11-02 00:05:42 +0000103
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900104 def escapeNum(self):
105 return False
Roger Meier85fb6de2012-11-02 00:05:42 +0000106
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900107 def __str__(self):
108 return self.__class__.__name__
Roger Meier0895dfe2012-12-26 22:09:55 +0100109
Roger Meier85fb6de2012-11-02 00:05:42 +0000110
111class JSONListContext(JSONBaseContext):
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900112
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900113 def doIO(self, function):
114 if self.first is True:
115 self.first = False
116 else:
117 function(COMMA)
Roger Meier85fb6de2012-11-02 00:05:42 +0000118
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900119 def write(self):
120 self.doIO(self.protocol.trans.write)
Roger Meier85fb6de2012-11-02 00:05:42 +0000121
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900122 def read(self):
123 self.doIO(self.protocol.readJSONSyntaxChar)
Roger Meier85fb6de2012-11-02 00:05:42 +0000124
125
126class JSONPairContext(JSONBaseContext):
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900127
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900128 def __init__(self, protocol):
129 super(JSONPairContext, self).__init__(protocol)
130 self.colon = True
Roger Meier85fb6de2012-11-02 00:05:42 +0000131
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900132 def doIO(self, function):
133 if self.first:
134 self.first = False
135 self.colon = True
136 else:
137 function(COLON if self.colon else COMMA)
138 self.colon = not self.colon
Roger Meier85fb6de2012-11-02 00:05:42 +0000139
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900140 def write(self):
141 self.doIO(self.protocol.trans.write)
Roger Meier85fb6de2012-11-02 00:05:42 +0000142
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900143 def read(self):
144 self.doIO(self.protocol.readJSONSyntaxChar)
Roger Meier85fb6de2012-11-02 00:05:42 +0000145
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900146 def escapeNum(self):
147 return self.colon
Roger Meier85fb6de2012-11-02 00:05:42 +0000148
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900149 def __str__(self):
150 return '%s, colon=%s' % (self.__class__.__name__, self.colon)
Roger Meier0895dfe2012-12-26 22:09:55 +0100151
Roger Meier85fb6de2012-11-02 00:05:42 +0000152
153class LookaheadReader():
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900154 hasData = False
155 data = ''
Roger Meier85fb6de2012-11-02 00:05:42 +0000156
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900157 def __init__(self, protocol):
158 self.protocol = protocol
Roger Meier85fb6de2012-11-02 00:05:42 +0000159
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900160 def read(self):
161 if self.hasData is True:
162 self.hasData = False
163 else:
164 self.data = self.protocol.trans.read(1)
165 return self.data
Roger Meier85fb6de2012-11-02 00:05:42 +0000166
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900167 def peek(self):
168 if self.hasData is False:
169 self.data = self.protocol.trans.read(1)
170 self.hasData = True
171 return self.data
Roger Meier85fb6de2012-11-02 00:05:42 +0000172
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900173
Roger Meier85fb6de2012-11-02 00:05:42 +0000174class TJSONProtocolBase(TProtocolBase):
175
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900176 def __init__(self, trans):
177 TProtocolBase.__init__(self, trans)
178 self.resetWriteContext()
179 self.resetReadContext()
Roger Meier85fb6de2012-11-02 00:05:42 +0000180
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900181 # We don't have length limit implementation for JSON protocols
182 @property
183 def string_length_limit(senf):
184 return None
Nobuaki Sukegawa7b545b52016-01-11 13:46:04 +0900185
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900186 @property
187 def container_length_limit(senf):
188 return None
Nobuaki Sukegawa7b545b52016-01-11 13:46:04 +0900189
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900190 def resetWriteContext(self):
191 self.context = JSONBaseContext(self)
192 self.contextStack = [self.context]
Roger Meier85fb6de2012-11-02 00:05:42 +0000193
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900194 def resetReadContext(self):
195 self.resetWriteContext()
196 self.reader = LookaheadReader(self)
Roger Meier85fb6de2012-11-02 00:05:42 +0000197
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900198 def pushContext(self, ctx):
199 self.contextStack.append(ctx)
200 self.context = ctx
Roger Meier85fb6de2012-11-02 00:05:42 +0000201
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900202 def popContext(self):
203 self.contextStack.pop()
204 if self.contextStack:
205 self.context = self.contextStack[-1]
Roger Meier85fb6de2012-11-02 00:05:42 +0000206 else:
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900207 self.context = JSONBaseContext(self)
208
209 def writeJSONString(self, string):
210 self.context.write()
211 json_str = ['"']
212 for s in string:
213 escaped = ESCAPE_CHAR_VALS.get(s, s)
214 json_str.append(escaped)
215 json_str.append('"')
216 self.trans.write(str_to_binary(''.join(json_str)))
217
218 def writeJSONNumber(self, number, formatter='{0}'):
219 self.context.write()
220 jsNumber = str(formatter.format(number)).encode('ascii')
221 if self.context.escapeNum():
222 self.trans.write(QUOTE)
223 self.trans.write(jsNumber)
224 self.trans.write(QUOTE)
225 else:
226 self.trans.write(jsNumber)
227
228 def writeJSONBase64(self, binary):
229 self.context.write()
230 self.trans.write(QUOTE)
231 self.trans.write(base64.b64encode(binary))
232 self.trans.write(QUOTE)
233
234 def writeJSONObjectStart(self):
235 self.context.write()
236 self.trans.write(LBRACE)
237 self.pushContext(JSONPairContext(self))
238
239 def writeJSONObjectEnd(self):
240 self.popContext()
241 self.trans.write(RBRACE)
242
243 def writeJSONArrayStart(self):
244 self.context.write()
245 self.trans.write(LBRACKET)
246 self.pushContext(JSONListContext(self))
247
248 def writeJSONArrayEnd(self):
249 self.popContext()
250 self.trans.write(RBRACKET)
251
252 def readJSONSyntaxChar(self, character):
253 current = self.reader.read()
254 if character != current:
Roger Meier85fb6de2012-11-02 00:05:42 +0000255 raise TProtocolException(TProtocolException.INVALID_DATA,
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900256 "Unexpected character: %s" % current)
Phongphan Phuttha7f01e2a2015-11-06 15:46:50 +0700257
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900258 def _isHighSurrogate(self, codeunit):
259 return codeunit >= 0xd800 and codeunit <= 0xdbff
Roger Meier85fb6de2012-11-02 00:05:42 +0000260
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900261 def _isLowSurrogate(self, codeunit):
262 return codeunit >= 0xdc00 and codeunit <= 0xdfff
Roger Meier85fb6de2012-11-02 00:05:42 +0000263
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900264 def _toChar(self, high, low=None):
265 if not low:
266 if sys.version_info[0] == 2:
267 return ("\\u%04x" % high).decode('unicode-escape') \
268 .encode('utf-8')
269 else:
270 return chr(high)
271 else:
272 codepoint = (1 << 16) + ((high & 0x3ff) << 10)
273 codepoint += low & 0x3ff
274 if sys.version_info[0] == 2:
275 s = "\\U%08x" % codepoint
276 return s.decode('unicode-escape').encode('utf-8')
277 else:
278 return chr(codepoint)
Roger Meier85fb6de2012-11-02 00:05:42 +0000279
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900280 def readJSONString(self, skipContext):
281 highSurrogate = None
282 string = []
283 if skipContext is False:
284 self.context.read()
Roger Meier85fb6de2012-11-02 00:05:42 +0000285 self.readJSONSyntaxChar(QUOTE)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900286 while True:
287 character = self.reader.read()
288 if character == QUOTE:
289 break
290 if ord(character) == ESCSEQ0:
291 character = self.reader.read()
292 if ord(character) == ESCSEQ1:
293 character = self.trans.read(4).decode('ascii')
294 codeunit = int(character, 16)
295 if self._isHighSurrogate(codeunit):
296 if highSurrogate:
297 raise TProtocolException(
298 TProtocolException.INVALID_DATA,
299 "Expected low surrogate char")
300 highSurrogate = codeunit
301 continue
302 elif self._isLowSurrogate(codeunit):
303 if not highSurrogate:
304 raise TProtocolException(
305 TProtocolException.INVALID_DATA,
306 "Expected high surrogate char")
307 character = self._toChar(highSurrogate, codeunit)
308 highSurrogate = None
309 else:
310 character = self._toChar(codeunit)
311 else:
312 if character not in ESCAPE_CHARS:
313 raise TProtocolException(
314 TProtocolException.INVALID_DATA,
315 "Expected control char")
316 character = ESCAPE_CHARS[character]
317 elif character in ESCAPE_CHAR_VALS:
318 raise TProtocolException(TProtocolException.INVALID_DATA,
319 "Unescaped control char")
320 elif sys.version_info[0] > 2:
321 utf8_bytes = bytearray([ord(character)])
322 while ord(self.reader.peek()) >= 0x80:
323 utf8_bytes.append(ord(self.reader.read()))
324 character = utf8_bytes.decode('utf8')
325 string.append(character)
Roger Meier85fb6de2012-11-02 00:05:42 +0000326
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900327 if highSurrogate:
328 raise TProtocolException(TProtocolException.INVALID_DATA,
329 "Expected low surrogate char")
330 return ''.join(string)
Roger Meier85fb6de2012-11-02 00:05:42 +0000331
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900332 def isJSONNumeric(self, character):
333 return (True if NUMERIC_CHAR.find(character) != - 1 else False)
Roger Meier85fb6de2012-11-02 00:05:42 +0000334
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900335 def readJSONQuotes(self):
336 if (self.context.escapeNum()):
337 self.readJSONSyntaxChar(QUOTE)
Roger Meier85fb6de2012-11-02 00:05:42 +0000338
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900339 def readJSONNumericChars(self):
340 numeric = []
341 while True:
342 character = self.reader.peek()
343 if self.isJSONNumeric(character) is False:
344 break
345 numeric.append(self.reader.read())
346 return b''.join(numeric).decode('ascii')
Roger Meier85fb6de2012-11-02 00:05:42 +0000347
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900348 def readJSONInteger(self):
349 self.context.read()
350 self.readJSONQuotes()
351 numeric = self.readJSONNumericChars()
352 self.readJSONQuotes()
353 try:
354 return int(numeric)
355 except ValueError:
356 raise TProtocolException(TProtocolException.INVALID_DATA,
357 "Bad data encounted in numeric data")
358
359 def readJSONDouble(self):
360 self.context.read()
361 if self.reader.peek() == QUOTE:
362 string = self.readJSONString(True)
363 try:
364 double = float(string)
365 if (self.context.escapeNum is False and
366 not math.isinf(double) and
367 not math.isnan(double)):
368 raise TProtocolException(
369 TProtocolException.INVALID_DATA,
370 "Numeric data unexpectedly quoted")
371 return double
372 except ValueError:
373 raise TProtocolException(TProtocolException.INVALID_DATA,
374 "Bad data encounted in numeric data")
375 else:
376 if self.context.escapeNum() is True:
377 self.readJSONSyntaxChar(QUOTE)
378 try:
379 return float(self.readJSONNumericChars())
380 except ValueError:
381 raise TProtocolException(TProtocolException.INVALID_DATA,
382 "Bad data encounted in numeric data")
383
384 def readJSONBase64(self):
385 string = self.readJSONString(False)
386 size = len(string)
387 m = size % 4
388 # Force padding since b64encode method does not allow it
389 if m != 0:
390 for i in range(4 - m):
391 string += '='
392 return base64.b64decode(string)
393
394 def readJSONObjectStart(self):
395 self.context.read()
396 self.readJSONSyntaxChar(LBRACE)
397 self.pushContext(JSONPairContext(self))
398
399 def readJSONObjectEnd(self):
400 self.readJSONSyntaxChar(RBRACE)
401 self.popContext()
402
403 def readJSONArrayStart(self):
404 self.context.read()
405 self.readJSONSyntaxChar(LBRACKET)
406 self.pushContext(JSONListContext(self))
407
408 def readJSONArrayEnd(self):
409 self.readJSONSyntaxChar(RBRACKET)
410 self.popContext()
Roger Meier85fb6de2012-11-02 00:05:42 +0000411
412
413class TJSONProtocol(TJSONProtocolBase):
414
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900415 def readMessageBegin(self):
416 self.resetReadContext()
417 self.readJSONArrayStart()
418 if self.readJSONInteger() != VERSION:
419 raise TProtocolException(TProtocolException.BAD_VERSION,
420 "Message contained bad version.")
421 name = self.readJSONString(False)
422 typen = self.readJSONInteger()
423 seqid = self.readJSONInteger()
424 return (name, typen, seqid)
Roger Meier85fb6de2012-11-02 00:05:42 +0000425
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900426 def readMessageEnd(self):
427 self.readJSONArrayEnd()
Roger Meier85fb6de2012-11-02 00:05:42 +0000428
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900429 def readStructBegin(self):
430 self.readJSONObjectStart()
Roger Meier85fb6de2012-11-02 00:05:42 +0000431
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900432 def readStructEnd(self):
433 self.readJSONObjectEnd()
Roger Meier85fb6de2012-11-02 00:05:42 +0000434
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900435 def readFieldBegin(self):
436 character = self.reader.peek()
437 ttype = 0
438 id = 0
439 if character == RBRACE:
440 ttype = TType.STOP
441 else:
442 id = self.readJSONInteger()
443 self.readJSONObjectStart()
444 ttype = JTYPES[self.readJSONString(False)]
445 return (None, ttype, id)
Roger Meier85fb6de2012-11-02 00:05:42 +0000446
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900447 def readFieldEnd(self):
448 self.readJSONObjectEnd()
Roger Meier85fb6de2012-11-02 00:05:42 +0000449
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900450 def readMapBegin(self):
451 self.readJSONArrayStart()
452 keyType = JTYPES[self.readJSONString(False)]
453 valueType = JTYPES[self.readJSONString(False)]
454 size = self.readJSONInteger()
455 self.readJSONObjectStart()
456 return (keyType, valueType, size)
Roger Meier85fb6de2012-11-02 00:05:42 +0000457
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900458 def readMapEnd(self):
459 self.readJSONObjectEnd()
460 self.readJSONArrayEnd()
Roger Meier85fb6de2012-11-02 00:05:42 +0000461
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900462 def readCollectionBegin(self):
463 self.readJSONArrayStart()
464 elemType = JTYPES[self.readJSONString(False)]
465 size = self.readJSONInteger()
466 return (elemType, size)
467 readListBegin = readCollectionBegin
468 readSetBegin = readCollectionBegin
Roger Meier85fb6de2012-11-02 00:05:42 +0000469
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900470 def readCollectionEnd(self):
471 self.readJSONArrayEnd()
472 readSetEnd = readCollectionEnd
473 readListEnd = readCollectionEnd
Roger Meier85fb6de2012-11-02 00:05:42 +0000474
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900475 def readBool(self):
476 return (False if self.readJSONInteger() == 0 else True)
Roger Meier85fb6de2012-11-02 00:05:42 +0000477
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900478 def readNumber(self):
479 return self.readJSONInteger()
480 readByte = readNumber
481 readI16 = readNumber
482 readI32 = readNumber
483 readI64 = readNumber
Roger Meier85fb6de2012-11-02 00:05:42 +0000484
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900485 def readDouble(self):
486 return self.readJSONDouble()
Roger Meier85fb6de2012-11-02 00:05:42 +0000487
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900488 def readString(self):
489 return self.readJSONString(False)
Roger Meier85fb6de2012-11-02 00:05:42 +0000490
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900491 def readBinary(self):
492 return self.readJSONBase64()
Roger Meier85fb6de2012-11-02 00:05:42 +0000493
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900494 def writeMessageBegin(self, name, request_type, seqid):
495 self.resetWriteContext()
496 self.writeJSONArrayStart()
497 self.writeJSONNumber(VERSION)
498 self.writeJSONString(name)
499 self.writeJSONNumber(request_type)
500 self.writeJSONNumber(seqid)
Roger Meier85fb6de2012-11-02 00:05:42 +0000501
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900502 def writeMessageEnd(self):
503 self.writeJSONArrayEnd()
Roger Meier85fb6de2012-11-02 00:05:42 +0000504
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900505 def writeStructBegin(self, name):
506 self.writeJSONObjectStart()
Roger Meier85fb6de2012-11-02 00:05:42 +0000507
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900508 def writeStructEnd(self):
509 self.writeJSONObjectEnd()
Roger Meier85fb6de2012-11-02 00:05:42 +0000510
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900511 def writeFieldBegin(self, name, ttype, id):
512 self.writeJSONNumber(id)
513 self.writeJSONObjectStart()
514 self.writeJSONString(CTYPES[ttype])
Roger Meier85fb6de2012-11-02 00:05:42 +0000515
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900516 def writeFieldEnd(self):
517 self.writeJSONObjectEnd()
Roger Meier85fb6de2012-11-02 00:05:42 +0000518
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900519 def writeFieldStop(self):
520 pass
Roger Meier85fb6de2012-11-02 00:05:42 +0000521
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900522 def writeMapBegin(self, ktype, vtype, size):
523 self.writeJSONArrayStart()
524 self.writeJSONString(CTYPES[ktype])
525 self.writeJSONString(CTYPES[vtype])
526 self.writeJSONNumber(size)
527 self.writeJSONObjectStart()
Roger Meier85fb6de2012-11-02 00:05:42 +0000528
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900529 def writeMapEnd(self):
530 self.writeJSONObjectEnd()
531 self.writeJSONArrayEnd()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900532
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900533 def writeListBegin(self, etype, size):
534 self.writeJSONArrayStart()
535 self.writeJSONString(CTYPES[etype])
536 self.writeJSONNumber(size)
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900537
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900538 def writeListEnd(self):
539 self.writeJSONArrayEnd()
Roger Meier85fb6de2012-11-02 00:05:42 +0000540
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900541 def writeSetBegin(self, etype, size):
542 self.writeJSONArrayStart()
543 self.writeJSONString(CTYPES[etype])
544 self.writeJSONNumber(size)
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900545
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900546 def writeSetEnd(self):
547 self.writeJSONArrayEnd()
Roger Meier85fb6de2012-11-02 00:05:42 +0000548
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900549 def writeBool(self, boolean):
550 self.writeJSONNumber(1 if boolean is True else 0)
Roger Meier85fb6de2012-11-02 00:05:42 +0000551
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900552 def writeByte(self, byte):
553 checkIntegerLimits(byte, 8)
554 self.writeJSONNumber(byte)
Konrad Grochowski93fea152014-10-02 16:29:14 +0200555
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900556 def writeI16(self, i16):
557 checkIntegerLimits(i16, 16)
558 self.writeJSONNumber(i16)
Konrad Grochowski93fea152014-10-02 16:29:14 +0200559
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900560 def writeI32(self, i32):
561 checkIntegerLimits(i32, 32)
562 self.writeJSONNumber(i32)
Konrad Grochowski93fea152014-10-02 16:29:14 +0200563
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900564 def writeI64(self, i64):
565 checkIntegerLimits(i64, 64)
566 self.writeJSONNumber(i64)
Roger Meier85fb6de2012-11-02 00:05:42 +0000567
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900568 def writeDouble(self, dbl):
569 # 17 significant digits should be just enough for any double precision
570 # value.
571 self.writeJSONNumber(dbl, '{0:.17g}')
Roger Meier85fb6de2012-11-02 00:05:42 +0000572
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900573 def writeString(self, string):
574 self.writeJSONString(string)
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900575
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900576 def writeBinary(self, binary):
577 self.writeJSONBase64(binary)
Roger Meier85fb6de2012-11-02 00:05:42 +0000578
Roger Meier0895dfe2012-12-26 22:09:55 +0100579
James E. King IIIe44f6a92019-02-07 17:11:21 -0500580class TJSONProtocolFactory(TProtocolFactory):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900581 def getProtocol(self, trans):
582 return TJSONProtocol(trans)
Roger Meier0895dfe2012-12-26 22:09:55 +0100583
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900584 @property
585 def string_length_limit(senf):
586 return None
Nobuaki Sukegawa7b545b52016-01-11 13:46:04 +0900587
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900588 @property
589 def container_length_limit(senf):
590 return None
Nobuaki Sukegawa7b545b52016-01-11 13:46:04 +0900591
Roger Meier0895dfe2012-12-26 22:09:55 +0100592
593class TSimpleJSONProtocol(TJSONProtocolBase):
594 """Simple, readable, write-only JSON protocol.
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900595
Roger Meier0895dfe2012-12-26 22:09:55 +0100596 Useful for interacting with scripting languages.
597 """
598
599 def readMessageBegin(self):
600 raise NotImplementedError()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900601
Roger Meier0895dfe2012-12-26 22:09:55 +0100602 def readMessageEnd(self):
603 raise NotImplementedError()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900604
Roger Meier0895dfe2012-12-26 22:09:55 +0100605 def readStructBegin(self):
606 raise NotImplementedError()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900607
Roger Meier0895dfe2012-12-26 22:09:55 +0100608 def readStructEnd(self):
609 raise NotImplementedError()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900610
Roger Meier0895dfe2012-12-26 22:09:55 +0100611 def writeMessageBegin(self, name, request_type, seqid):
612 self.resetWriteContext()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900613
Roger Meier0895dfe2012-12-26 22:09:55 +0100614 def writeMessageEnd(self):
615 pass
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900616
Roger Meier0895dfe2012-12-26 22:09:55 +0100617 def writeStructBegin(self, name):
618 self.writeJSONObjectStart()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900619
Roger Meier0895dfe2012-12-26 22:09:55 +0100620 def writeStructEnd(self):
621 self.writeJSONObjectEnd()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900622
Roger Meier0895dfe2012-12-26 22:09:55 +0100623 def writeFieldBegin(self, name, ttype, fid):
624 self.writeJSONString(name)
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900625
Roger Meier0895dfe2012-12-26 22:09:55 +0100626 def writeFieldEnd(self):
627 pass
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900628
Roger Meier0895dfe2012-12-26 22:09:55 +0100629 def writeMapBegin(self, ktype, vtype, size):
630 self.writeJSONObjectStart()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900631
Roger Meier0895dfe2012-12-26 22:09:55 +0100632 def writeMapEnd(self):
633 self.writeJSONObjectEnd()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900634
Roger Meier0895dfe2012-12-26 22:09:55 +0100635 def _writeCollectionBegin(self, etype, size):
636 self.writeJSONArrayStart()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900637
Roger Meier0895dfe2012-12-26 22:09:55 +0100638 def _writeCollectionEnd(self):
639 self.writeJSONArrayEnd()
640 writeListBegin = _writeCollectionBegin
641 writeListEnd = _writeCollectionEnd
642 writeSetBegin = _writeCollectionBegin
643 writeSetEnd = _writeCollectionEnd
644
Konrad Grochowski93fea152014-10-02 16:29:14 +0200645 def writeByte(self, byte):
646 checkIntegerLimits(byte, 8)
647 self.writeJSONNumber(byte)
648
649 def writeI16(self, i16):
650 checkIntegerLimits(i16, 16)
651 self.writeJSONNumber(i16)
652
653 def writeI32(self, i32):
654 checkIntegerLimits(i32, 32)
655 self.writeJSONNumber(i32)
656
657 def writeI64(self, i64):
658 checkIntegerLimits(i64, 64)
659 self.writeJSONNumber(i64)
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900660
Roger Meier0895dfe2012-12-26 22:09:55 +0100661 def writeBool(self, boolean):
662 self.writeJSONNumber(1 if boolean is True else 0)
663
664 def writeDouble(self, dbl):
665 self.writeJSONNumber(dbl)
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900666
Roger Meier0895dfe2012-12-26 22:09:55 +0100667 def writeString(self, string):
668 self.writeJSONString(string)
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900669
Roger Meier0895dfe2012-12-26 22:09:55 +0100670 def writeBinary(self, binary):
671 self.writeJSONBase64(binary)
672
673
James E. King IIIe44f6a92019-02-07 17:11:21 -0500674class TSimpleJSONProtocolFactory(TProtocolFactory):
Roger Meier0895dfe2012-12-26 22:09:55 +0100675
676 def getProtocol(self, trans):
677 return TSimpleJSONProtocol(trans)