blob: f9e65fbf20f3de62fe247cddf8f03b7db1db8ac0 [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 Sukegawa760511f2015-11-06 21:24:16 +090020from .TProtocol import TType, TProtocolBase, TProtocolException, checkIntegerLimits
Roger Meier0895dfe2012-12-26 22:09:55 +010021import base64
Roger Meier0895dfe2012-12-26 22:09:55 +010022import math
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +090023import sys
24
25from ..compat import str_to_binary
26
Roger Meier85fb6de2012-11-02 00:05:42 +000027
Roger Meier0895dfe2012-12-26 22:09:55 +010028__all__ = ['TJSONProtocol',
29 'TJSONProtocolFactory',
30 'TSimpleJSONProtocol',
31 'TSimpleJSONProtocolFactory']
Roger Meier85fb6de2012-11-02 00:05:42 +000032
33VERSION = 1
34
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +090035COMMA = b','
36COLON = b':'
37LBRACE = b'{'
38RBRACE = b'}'
39LBRACKET = b'['
40RBRACKET = b']'
41QUOTE = b'"'
42BACKSLASH = b'\\'
43ZERO = b'0'
Roger Meier85fb6de2012-11-02 00:05:42 +000044
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +090045ESCSEQ0 = ord('\\')
46ESCSEQ1 = ord('u')
47ESCAPE_CHAR_VALS = {
48 '"': '\\"',
49 '\\': '\\\\',
50 '\b': '\\b',
51 '\f': '\\f',
52 '\n': '\\n',
53 '\r': '\\r',
54 '\t': '\\t',
55 # '/': '\\/',
56}
57ESCAPE_CHARS = {
58 b'"': '"',
59 b'\\': '\\',
60 b'b': '\b',
61 b'f': '\f',
62 b'n': '\n',
63 b'r': '\r',
64 b't': '\t',
65 b'/': '/',
66}
67NUMERIC_CHAR = b'+-.0123456789Ee'
Roger Meier85fb6de2012-11-02 00:05:42 +000068
69CTYPES = {TType.BOOL: 'tf',
70 TType.BYTE: 'i8',
71 TType.I16: 'i16',
72 TType.I32: 'i32',
73 TType.I64: 'i64',
74 TType.DOUBLE: 'dbl',
75 TType.STRING: 'str',
Roger Meier05ab89a2012-11-02 10:36:59 +000076 TType.STRUCT: 'rec',
Roger Meier85fb6de2012-11-02 00:05:42 +000077 TType.LIST: 'lst',
78 TType.SET: 'set',
79 TType.MAP: 'map'}
80
81JTYPES = {}
82for key in CTYPES.keys():
83 JTYPES[CTYPES[key]] = key
84
85
Roger Meierad8154a2012-12-18 21:02:16 +010086class JSONBaseContext(object):
Roger Meier85fb6de2012-11-02 00:05:42 +000087
88 def __init__(self, protocol):
89 self.protocol = protocol
90 self.first = True
91
92 def doIO(self, function):
93 pass
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +090094
Roger Meier85fb6de2012-11-02 00:05:42 +000095 def write(self):
96 pass
97
98 def read(self):
99 pass
100
101 def escapeNum(self):
102 return False
103
Roger Meier0895dfe2012-12-26 22:09:55 +0100104 def __str__(self):
105 return self.__class__.__name__
106
Roger Meier85fb6de2012-11-02 00:05:42 +0000107
108class JSONListContext(JSONBaseContext):
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900109
Roger Meier85fb6de2012-11-02 00:05:42 +0000110 def doIO(self, function):
111 if self.first is True:
112 self.first = False
113 else:
114 function(COMMA)
115
116 def write(self):
117 self.doIO(self.protocol.trans.write)
118
119 def read(self):
120 self.doIO(self.protocol.readJSONSyntaxChar)
121
122
123class JSONPairContext(JSONBaseContext):
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900124
Roger Meier0895dfe2012-12-26 22:09:55 +0100125 def __init__(self, protocol):
126 super(JSONPairContext, self).__init__(protocol)
127 self.colon = True
Roger Meier85fb6de2012-11-02 00:05:42 +0000128
129 def doIO(self, function):
Roger Meier0895dfe2012-12-26 22:09:55 +0100130 if self.first:
Roger Meier85fb6de2012-11-02 00:05:42 +0000131 self.first = False
132 self.colon = True
133 else:
Roger Meier0895dfe2012-12-26 22:09:55 +0100134 function(COLON if self.colon else COMMA)
Roger Meier85fb6de2012-11-02 00:05:42 +0000135 self.colon = not self.colon
136
137 def write(self):
138 self.doIO(self.protocol.trans.write)
139
140 def read(self):
141 self.doIO(self.protocol.readJSONSyntaxChar)
142
143 def escapeNum(self):
144 return self.colon
145
Roger Meier0895dfe2012-12-26 22:09:55 +0100146 def __str__(self):
147 return '%s, colon=%s' % (self.__class__.__name__, self.colon)
148
Roger Meier85fb6de2012-11-02 00:05:42 +0000149
150class LookaheadReader():
151 hasData = False
152 data = ''
153
154 def __init__(self, protocol):
155 self.protocol = protocol
156
157 def read(self):
158 if self.hasData is True:
159 self.hasData = False
160 else:
161 self.data = self.protocol.trans.read(1)
162 return self.data
163
164 def peek(self):
165 if self.hasData is False:
166 self.data = self.protocol.trans.read(1)
167 self.hasData = True
168 return self.data
169
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900170
Roger Meier85fb6de2012-11-02 00:05:42 +0000171class TJSONProtocolBase(TProtocolBase):
172
173 def __init__(self, trans):
174 TProtocolBase.__init__(self, trans)
Roger Meierad8154a2012-12-18 21:02:16 +0100175 self.resetWriteContext()
176 self.resetReadContext()
Roger Meier85fb6de2012-11-02 00:05:42 +0000177
Nobuaki Sukegawa7b545b52016-01-11 13:46:04 +0900178 # We don't have length limit implementation for JSON protocols
179 @property
180 def string_length_limit(senf):
181 return None
182
183 @property
184 def container_length_limit(senf):
185 return None
186
Roger Meier85fb6de2012-11-02 00:05:42 +0000187 def resetWriteContext(self):
Roger Meier0895dfe2012-12-26 22:09:55 +0100188 self.context = JSONBaseContext(self)
189 self.contextStack = [self.context]
Roger Meier85fb6de2012-11-02 00:05:42 +0000190
191 def resetReadContext(self):
192 self.resetWriteContext()
193 self.reader = LookaheadReader(self)
194
195 def pushContext(self, ctx):
196 self.contextStack.append(ctx)
197 self.context = ctx
198
199 def popContext(self):
200 self.contextStack.pop()
Roger Meier0895dfe2012-12-26 22:09:55 +0100201 if self.contextStack:
202 self.context = self.contextStack[-1]
203 else:
204 self.context = JSONBaseContext(self)
Roger Meier85fb6de2012-11-02 00:05:42 +0000205
206 def writeJSONString(self, string):
207 self.context.write()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900208 json_str = ['"']
209 for s in string:
210 escaped = ESCAPE_CHAR_VALS.get(s, s)
211 json_str.append(escaped)
212 json_str.append('"')
213 self.trans.write(str_to_binary(''.join(json_str)))
Roger Meier85fb6de2012-11-02 00:05:42 +0000214
Nobuaki Sukegawa33744b02016-01-03 14:24:39 +0900215 def writeJSONNumber(self, number, formatter='{0}'):
Roger Meier85fb6de2012-11-02 00:05:42 +0000216 self.context.write()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900217 jsNumber = str(formatter.format(number)).encode('ascii')
Roger Meier85fb6de2012-11-02 00:05:42 +0000218 if self.context.escapeNum():
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900219 self.trans.write(QUOTE)
220 self.trans.write(jsNumber)
221 self.trans.write(QUOTE)
222 else:
223 self.trans.write(jsNumber)
Roger Meier85fb6de2012-11-02 00:05:42 +0000224
225 def writeJSONBase64(self, binary):
226 self.context.write()
227 self.trans.write(QUOTE)
228 self.trans.write(base64.b64encode(binary))
229 self.trans.write(QUOTE)
230
231 def writeJSONObjectStart(self):
232 self.context.write()
233 self.trans.write(LBRACE)
234 self.pushContext(JSONPairContext(self))
235
236 def writeJSONObjectEnd(self):
237 self.popContext()
238 self.trans.write(RBRACE)
239
240 def writeJSONArrayStart(self):
241 self.context.write()
242 self.trans.write(LBRACKET)
243 self.pushContext(JSONListContext(self))
244
245 def writeJSONArrayEnd(self):
246 self.popContext()
247 self.trans.write(RBRACKET)
248
249 def readJSONSyntaxChar(self, character):
250 current = self.reader.read()
251 if character != current:
252 raise TProtocolException(TProtocolException.INVALID_DATA,
253 "Unexpected character: %s" % current)
254
Phongphan Phuttha7f01e2a2015-11-06 15:46:50 +0700255 def _isHighSurrogate(self, codeunit):
256 return codeunit >= 0xd800 and codeunit <= 0xdbff
257
258 def _isLowSurrogate(self, codeunit):
259 return codeunit >= 0xdc00 and codeunit <= 0xdfff
260
Phongphan Phuttha369d62e2015-11-09 02:05:09 +0700261 def _toChar(self, high, low=None):
262 if not low:
Nobuaki Sukegawa8551f3f2015-11-15 16:33:14 +0900263 if sys.version_info[0] == 2:
264 return ("\\u%04x" % high).decode('unicode-escape').encode('utf-8')
265 else:
266 return chr(high)
Phongphan Phuttha369d62e2015-11-09 02:05:09 +0700267 else:
268 codepoint = (1 << 16) + ((high & 0x3ff) << 10)
269 codepoint += low & 0x3ff
Nobuaki Sukegawa8551f3f2015-11-15 16:33:14 +0900270 if sys.version_info[0] == 2:
271 s = "\\U%08x" % codepoint
272 return s.decode('unicode-escape').encode('utf-8')
273 else:
274 return chr(codepoint)
Phongphan Phuttha369d62e2015-11-09 02:05:09 +0700275
Roger Meier85fb6de2012-11-02 00:05:42 +0000276 def readJSONString(self, skipContext):
Phongphan Phuttha7f01e2a2015-11-06 15:46:50 +0700277 highSurrogate = None
Roger Meier85fb6de2012-11-02 00:05:42 +0000278 string = []
279 if skipContext is False:
280 self.context.read()
281 self.readJSONSyntaxChar(QUOTE)
282 while True:
283 character = self.reader.read()
284 if character == QUOTE:
285 break
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900286 if ord(character) == ESCSEQ0:
Roger Meier85fb6de2012-11-02 00:05:42 +0000287 character = self.reader.read()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900288 if ord(character) == ESCSEQ1:
Phongphan Phuttha369d62e2015-11-09 02:05:09 +0700289 character = self.trans.read(4).decode('ascii')
290 codeunit = int(character, 16)
291 if self._isHighSurrogate(codeunit):
292 if highSurrogate:
293 raise TProtocolException(TProtocolException.INVALID_DATA,
294 "Expected low surrogate char")
295 highSurrogate = codeunit
296 continue
297 elif self._isLowSurrogate(codeunit):
298 if not highSurrogate:
299 raise TProtocolException(TProtocolException.INVALID_DATA,
300 "Expected high surrogate char")
301 character = self._toChar(highSurrogate, codeunit)
302 highSurrogate = None
Phongphan Phuttha7f01e2a2015-11-06 15:46:50 +0700303 else:
Phongphan Phuttha369d62e2015-11-09 02:05:09 +0700304 character = self._toChar(codeunit)
Roger Meier85fb6de2012-11-02 00:05:42 +0000305 else:
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900306 if character not in ESCAPE_CHARS:
Roger Meier85fb6de2012-11-02 00:05:42 +0000307 raise TProtocolException(TProtocolException.INVALID_DATA,
308 "Expected control char")
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900309 character = ESCAPE_CHARS[character]
310 elif character in ESCAPE_CHAR_VALS:
311 raise TProtocolException(TProtocolException.INVALID_DATA,
312 "Unescaped control char")
313 elif sys.version_info[0] > 2:
314 utf8_bytes = bytearray([ord(character)])
315 while ord(self.reader.peek()) >= 0x80:
316 utf8_bytes.append(ord(self.reader.read()))
317 character = utf8_bytes.decode('utf8')
Roger Meier85fb6de2012-11-02 00:05:42 +0000318 string.append(character)
Phongphan Phuttha7f01e2a2015-11-06 15:46:50 +0700319
320 if highSurrogate:
321 raise TProtocolException(TProtocolException.INVALID_DATA,
322 "Expected low surrogate char")
Roger Meier85fb6de2012-11-02 00:05:42 +0000323 return ''.join(string)
324
325 def isJSONNumeric(self, character):
326 return (True if NUMERIC_CHAR.find(character) != - 1 else False)
327
328 def readJSONQuotes(self):
329 if (self.context.escapeNum()):
330 self.readJSONSyntaxChar(QUOTE)
331
332 def readJSONNumericChars(self):
333 numeric = []
334 while True:
335 character = self.reader.peek()
336 if self.isJSONNumeric(character) is False:
337 break
338 numeric.append(self.reader.read())
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900339 return b''.join(numeric).decode('ascii')
Roger Meier85fb6de2012-11-02 00:05:42 +0000340
341 def readJSONInteger(self):
342 self.context.read()
343 self.readJSONQuotes()
344 numeric = self.readJSONNumericChars()
345 self.readJSONQuotes()
346 try:
347 return int(numeric)
348 except ValueError:
349 raise TProtocolException(TProtocolException.INVALID_DATA,
350 "Bad data encounted in numeric data")
351
352 def readJSONDouble(self):
353 self.context.read()
354 if self.reader.peek() == QUOTE:
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900355 string = self.readJSONString(True)
Roger Meier85fb6de2012-11-02 00:05:42 +0000356 try:
357 double = float(string)
Roger Meier0895dfe2012-12-26 22:09:55 +0100358 if (self.context.escapeNum is False and
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900359 not math.isinf(double) and
360 not math.isnan(double)):
Roger Meier85fb6de2012-11-02 00:05:42 +0000361 raise TProtocolException(TProtocolException.INVALID_DATA,
362 "Numeric data unexpectedly quoted")
363 return double
364 except ValueError:
365 raise TProtocolException(TProtocolException.INVALID_DATA,
366 "Bad data encounted in numeric data")
367 else:
368 if self.context.escapeNum() is True:
369 self.readJSONSyntaxChar(QUOTE)
370 try:
371 return float(self.readJSONNumericChars())
Roger Meierad8154a2012-12-18 21:02:16 +0100372 except ValueError:
Roger Meier85fb6de2012-11-02 00:05:42 +0000373 raise TProtocolException(TProtocolException.INVALID_DATA,
374 "Bad data encounted in numeric data")
375
376 def readJSONBase64(self):
377 string = self.readJSONString(False)
Nobuaki Sukegawabc7e4802015-11-14 19:23:27 +0900378 size = len(string)
379 m = size % 4
380 # Force padding since b64encode method does not allow it
381 if m != 0:
382 for i in range(4 - m):
383 string += '='
Roger Meier85fb6de2012-11-02 00:05:42 +0000384 return base64.b64decode(string)
385
386 def readJSONObjectStart(self):
387 self.context.read()
388 self.readJSONSyntaxChar(LBRACE)
389 self.pushContext(JSONPairContext(self))
390
391 def readJSONObjectEnd(self):
392 self.readJSONSyntaxChar(RBRACE)
393 self.popContext()
394
395 def readJSONArrayStart(self):
396 self.context.read()
397 self.readJSONSyntaxChar(LBRACKET)
398 self.pushContext(JSONListContext(self))
399
400 def readJSONArrayEnd(self):
401 self.readJSONSyntaxChar(RBRACKET)
402 self.popContext()
403
404
405class TJSONProtocol(TJSONProtocolBase):
406
407 def readMessageBegin(self):
408 self.resetReadContext()
409 self.readJSONArrayStart()
410 if self.readJSONInteger() != VERSION:
411 raise TProtocolException(TProtocolException.BAD_VERSION,
412 "Message contained bad version.")
413 name = self.readJSONString(False)
414 typen = self.readJSONInteger()
415 seqid = self.readJSONInteger()
416 return (name, typen, seqid)
417
418 def readMessageEnd(self):
419 self.readJSONArrayEnd()
420
421 def readStructBegin(self):
422 self.readJSONObjectStart()
423
424 def readStructEnd(self):
425 self.readJSONObjectEnd()
426
427 def readFieldBegin(self):
428 character = self.reader.peek()
Roger Meierad8154a2012-12-18 21:02:16 +0100429 ttype = 0
Roger Meier85fb6de2012-11-02 00:05:42 +0000430 id = 0
431 if character == RBRACE:
Roger Meierad8154a2012-12-18 21:02:16 +0100432 ttype = TType.STOP
Roger Meier85fb6de2012-11-02 00:05:42 +0000433 else:
434 id = self.readJSONInteger()
435 self.readJSONObjectStart()
Roger Meierad8154a2012-12-18 21:02:16 +0100436 ttype = JTYPES[self.readJSONString(False)]
437 return (None, ttype, id)
Roger Meier85fb6de2012-11-02 00:05:42 +0000438
439 def readFieldEnd(self):
440 self.readJSONObjectEnd()
441
442 def readMapBegin(self):
443 self.readJSONArrayStart()
444 keyType = JTYPES[self.readJSONString(False)]
445 valueType = JTYPES[self.readJSONString(False)]
446 size = self.readJSONInteger()
447 self.readJSONObjectStart()
448 return (keyType, valueType, size)
449
450 def readMapEnd(self):
451 self.readJSONObjectEnd()
452 self.readJSONArrayEnd()
453
454 def readCollectionBegin(self):
455 self.readJSONArrayStart()
456 elemType = JTYPES[self.readJSONString(False)]
457 size = self.readJSONInteger()
Roger Meierad8154a2012-12-18 21:02:16 +0100458 return (elemType, size)
Roger Meier85fb6de2012-11-02 00:05:42 +0000459 readListBegin = readCollectionBegin
460 readSetBegin = readCollectionBegin
461
462 def readCollectionEnd(self):
463 self.readJSONArrayEnd()
464 readSetEnd = readCollectionEnd
465 readListEnd = readCollectionEnd
466
467 def readBool(self):
468 return (False if self.readJSONInteger() == 0 else True)
469
470 def readNumber(self):
471 return self.readJSONInteger()
472 readByte = readNumber
473 readI16 = readNumber
474 readI32 = readNumber
475 readI64 = readNumber
476
477 def readDouble(self):
478 return self.readJSONDouble()
479
480 def readString(self):
481 return self.readJSONString(False)
482
483 def readBinary(self):
484 return self.readJSONBase64()
485
486 def writeMessageBegin(self, name, request_type, seqid):
487 self.resetWriteContext()
488 self.writeJSONArrayStart()
489 self.writeJSONNumber(VERSION)
490 self.writeJSONString(name)
491 self.writeJSONNumber(request_type)
492 self.writeJSONNumber(seqid)
493
494 def writeMessageEnd(self):
495 self.writeJSONArrayEnd()
496
497 def writeStructBegin(self, name):
498 self.writeJSONObjectStart()
499
500 def writeStructEnd(self):
501 self.writeJSONObjectEnd()
502
Roger Meierad8154a2012-12-18 21:02:16 +0100503 def writeFieldBegin(self, name, ttype, id):
Roger Meier85fb6de2012-11-02 00:05:42 +0000504 self.writeJSONNumber(id)
505 self.writeJSONObjectStart()
Roger Meierad8154a2012-12-18 21:02:16 +0100506 self.writeJSONString(CTYPES[ttype])
Roger Meier85fb6de2012-11-02 00:05:42 +0000507
508 def writeFieldEnd(self):
509 self.writeJSONObjectEnd()
510
511 def writeFieldStop(self):
512 pass
513
514 def writeMapBegin(self, ktype, vtype, size):
515 self.writeJSONArrayStart()
516 self.writeJSONString(CTYPES[ktype])
517 self.writeJSONString(CTYPES[vtype])
518 self.writeJSONNumber(size)
519 self.writeJSONObjectStart()
520
521 def writeMapEnd(self):
522 self.writeJSONObjectEnd()
523 self.writeJSONArrayEnd()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900524
Roger Meier85fb6de2012-11-02 00:05:42 +0000525 def writeListBegin(self, etype, size):
526 self.writeJSONArrayStart()
527 self.writeJSONString(CTYPES[etype])
528 self.writeJSONNumber(size)
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900529
Roger Meier85fb6de2012-11-02 00:05:42 +0000530 def writeListEnd(self):
531 self.writeJSONArrayEnd()
532
533 def writeSetBegin(self, etype, size):
534 self.writeJSONArrayStart()
535 self.writeJSONString(CTYPES[etype])
536 self.writeJSONNumber(size)
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900537
Roger Meier85fb6de2012-11-02 00:05:42 +0000538 def writeSetEnd(self):
539 self.writeJSONArrayEnd()
540
541 def writeBool(self, boolean):
542 self.writeJSONNumber(1 if boolean is True else 0)
543
Konrad Grochowski93fea152014-10-02 16:29:14 +0200544 def writeByte(self, byte):
545 checkIntegerLimits(byte, 8)
546 self.writeJSONNumber(byte)
547
548 def writeI16(self, i16):
549 checkIntegerLimits(i16, 16)
550 self.writeJSONNumber(i16)
551
552 def writeI32(self, i32):
553 checkIntegerLimits(i32, 32)
554 self.writeJSONNumber(i32)
555
556 def writeI64(self, i64):
557 checkIntegerLimits(i64, 64)
558 self.writeJSONNumber(i64)
Roger Meier85fb6de2012-11-02 00:05:42 +0000559
560 def writeDouble(self, dbl):
Nobuaki Sukegawa228b3282015-10-10 03:11:49 +0900561 # 17 significant digits should be just enough for any double precision value.
Nobuaki Sukegawa33744b02016-01-03 14:24:39 +0900562 self.writeJSONNumber(dbl, '{0:.17g}')
Roger Meier85fb6de2012-11-02 00:05:42 +0000563
564 def writeString(self, string):
565 self.writeJSONString(string)
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900566
Roger Meier85fb6de2012-11-02 00:05:42 +0000567 def writeBinary(self, binary):
568 self.writeJSONBase64(binary)
569
Roger Meier0895dfe2012-12-26 22:09:55 +0100570
Nobuaki Sukegawab9c859a2015-12-21 01:10:25 +0900571class TJSONProtocolFactory(object):
Roger Meier85fb6de2012-11-02 00:05:42 +0000572 def getProtocol(self, trans):
573 return TJSONProtocol(trans)
Roger Meier0895dfe2012-12-26 22:09:55 +0100574
Nobuaki Sukegawa7b545b52016-01-11 13:46:04 +0900575 @property
576 def string_length_limit(senf):
577 return None
578
579 @property
580 def container_length_limit(senf):
581 return None
582
Roger Meier0895dfe2012-12-26 22:09:55 +0100583
584class TSimpleJSONProtocol(TJSONProtocolBase):
585 """Simple, readable, write-only JSON protocol.
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900586
Roger Meier0895dfe2012-12-26 22:09:55 +0100587 Useful for interacting with scripting languages.
588 """
589
590 def readMessageBegin(self):
591 raise NotImplementedError()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900592
Roger Meier0895dfe2012-12-26 22:09:55 +0100593 def readMessageEnd(self):
594 raise NotImplementedError()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900595
Roger Meier0895dfe2012-12-26 22:09:55 +0100596 def readStructBegin(self):
597 raise NotImplementedError()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900598
Roger Meier0895dfe2012-12-26 22:09:55 +0100599 def readStructEnd(self):
600 raise NotImplementedError()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900601
Roger Meier0895dfe2012-12-26 22:09:55 +0100602 def writeMessageBegin(self, name, request_type, seqid):
603 self.resetWriteContext()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900604
Roger Meier0895dfe2012-12-26 22:09:55 +0100605 def writeMessageEnd(self):
606 pass
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900607
Roger Meier0895dfe2012-12-26 22:09:55 +0100608 def writeStructBegin(self, name):
609 self.writeJSONObjectStart()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900610
Roger Meier0895dfe2012-12-26 22:09:55 +0100611 def writeStructEnd(self):
612 self.writeJSONObjectEnd()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900613
Roger Meier0895dfe2012-12-26 22:09:55 +0100614 def writeFieldBegin(self, name, ttype, fid):
615 self.writeJSONString(name)
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900616
Roger Meier0895dfe2012-12-26 22:09:55 +0100617 def writeFieldEnd(self):
618 pass
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900619
Roger Meier0895dfe2012-12-26 22:09:55 +0100620 def writeMapBegin(self, ktype, vtype, size):
621 self.writeJSONObjectStart()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900622
Roger Meier0895dfe2012-12-26 22:09:55 +0100623 def writeMapEnd(self):
624 self.writeJSONObjectEnd()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900625
Roger Meier0895dfe2012-12-26 22:09:55 +0100626 def _writeCollectionBegin(self, etype, size):
627 self.writeJSONArrayStart()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900628
Roger Meier0895dfe2012-12-26 22:09:55 +0100629 def _writeCollectionEnd(self):
630 self.writeJSONArrayEnd()
631 writeListBegin = _writeCollectionBegin
632 writeListEnd = _writeCollectionEnd
633 writeSetBegin = _writeCollectionBegin
634 writeSetEnd = _writeCollectionEnd
635
Konrad Grochowski93fea152014-10-02 16:29:14 +0200636 def writeByte(self, byte):
637 checkIntegerLimits(byte, 8)
638 self.writeJSONNumber(byte)
639
640 def writeI16(self, i16):
641 checkIntegerLimits(i16, 16)
642 self.writeJSONNumber(i16)
643
644 def writeI32(self, i32):
645 checkIntegerLimits(i32, 32)
646 self.writeJSONNumber(i32)
647
648 def writeI64(self, i64):
649 checkIntegerLimits(i64, 64)
650 self.writeJSONNumber(i64)
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900651
Roger Meier0895dfe2012-12-26 22:09:55 +0100652 def writeBool(self, boolean):
653 self.writeJSONNumber(1 if boolean is True else 0)
654
655 def writeDouble(self, dbl):
656 self.writeJSONNumber(dbl)
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900657
Roger Meier0895dfe2012-12-26 22:09:55 +0100658 def writeString(self, string):
659 self.writeJSONString(string)
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900660
Roger Meier0895dfe2012-12-26 22:09:55 +0100661 def writeBinary(self, binary):
662 self.writeJSONBase64(binary)
663
664
665class TSimpleJSONProtocolFactory(object):
666
667 def getProtocol(self, trans):
668 return TSimpleJSONProtocol(trans)