thrift-json 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ thrift-rb-json
2
+ ==============
3
+
4
+ The current Thrift gem doesn't include the JsonProtocol library. I've pulled it out of the Apache SVN repo, and made it a gem.
5
+
@@ -0,0 +1,3 @@
1
+ require 'thrift' unless defined?(Thrift::BaseProtocol)
2
+
3
+ require File.join(File.dirname(__FILE__), 'thrift/json_protocol')
@@ -0,0 +1,756 @@
1
+ #
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
+
20
+ @@kJSONObjectStart = '{'
21
+ @@kJSONObjectEnd = '}'
22
+ @@kJSONArrayStart = '['
23
+ @@kJSONArrayEnd = ']'
24
+ @@kJSONNewline = '\n'
25
+ @@kJSONElemSeparator = ','
26
+ @@kJSONPairSeparator = ':'
27
+ @@kJSONBackslash = '\\'
28
+ @@kJSONStringDelimiter = '"'
29
+
30
+ @@kThriftVersion1 = 1
31
+
32
+ @@kThriftNan = "NaN"
33
+ @@kThriftInfinity = "Infinity"
34
+ @@kThriftNegativeInfinity = "-Infinity"
35
+
36
+ module Thrift
37
+ class LookaheadReader
38
+ def initialize(trans)
39
+ @trans = trans
40
+ @hasData = false
41
+ @data = nil
42
+ end
43
+
44
+ def read
45
+ if @hasData
46
+ @hasData = false
47
+ else
48
+ @data = @trans.read(1)
49
+ end
50
+
51
+ return @data
52
+ end
53
+
54
+ def peek
55
+ if !@hasData
56
+ @data = @trans.read(1)
57
+ end
58
+ @hasData = true
59
+ return @data
60
+ end
61
+ end
62
+
63
+ #
64
+ # Class to serve as base JSON context and as base class for other context
65
+ # implementations
66
+ #
67
+ class JSONContext
68
+ #
69
+ # Write context data to the trans. Default is to do nothing.
70
+ #
71
+ def write(trans)
72
+ end
73
+
74
+ #
75
+ # Read context data from the trans. Default is to do nothing.
76
+ #
77
+ def read(reader)
78
+ end
79
+
80
+ #
81
+ # Return true if numbers need to be escaped as strings in this context.
82
+ # Default behavior is to return false.
83
+ #
84
+ def escapeNum
85
+ return false
86
+ end
87
+ end
88
+
89
+ # Context class for object member key-value pairs
90
+ class JSONPairContext < JSONContext
91
+ def initialize
92
+ @first = true
93
+ @colon = true
94
+ end
95
+
96
+ def write(trans)
97
+ if (@first)
98
+ @first = false
99
+ @colon = true
100
+ else
101
+ trans.write(@colon ? @@kJSONPairSeparator : @@kJSONElemSeparator)
102
+ @colon = !@colon
103
+ end
104
+ end
105
+
106
+ def read(reader)
107
+ if (@first)
108
+ @first = false
109
+ @colon = true
110
+ else
111
+ ch = (@colon ? @@kJSONPairSeparator : @@kJSONElemSeparator)
112
+ @colon = !@colon
113
+ JsonProtocol::read_syntax_char(reader, ch)
114
+ end
115
+ end
116
+
117
+ # Numbers must be turned into strings if they are the key part of a pair
118
+ def escapeNum
119
+ return @colon
120
+ end
121
+ end
122
+
123
+ # Context class for lists
124
+ class JSONListContext < JSONContext
125
+
126
+ def initialize
127
+ @first = true
128
+ end
129
+
130
+ def write(trans)
131
+ if (@first)
132
+ @first = false
133
+ else
134
+ trans.write(@@kJSONElemSeparator)
135
+ end
136
+ end
137
+
138
+ def read(reader)
139
+ if (@first)
140
+ @first = false
141
+ else
142
+ JsonProtocol::read_syntax_char(reader, @@kJSONElemSeparator)
143
+ end
144
+ end
145
+ end
146
+
147
+ class JsonProtocol < BaseProtocol
148
+ def initialize(trans)
149
+ super(trans)
150
+ @context = JSONContext.new
151
+ @contexts = Array.new
152
+ @reader = LookaheadReader.new(trans)
153
+ end
154
+
155
+ def get_type_name_for_type_id(id)
156
+ case id
157
+ when Types::BOOL
158
+ "tf"
159
+ when Types::BYTE
160
+ "i8"
161
+ when Types::I16
162
+ "i16"
163
+ when Types::I32
164
+ "i32"
165
+ when Types::I64
166
+ "i64"
167
+ when Types::DOUBLE
168
+ "dbl"
169
+ when Types::STRING
170
+ "str"
171
+ when Types::STRUCT
172
+ "rec"
173
+ when Types::MAP
174
+ "map"
175
+ when Types::SET
176
+ "set"
177
+ when Types::LIST
178
+ "lst"
179
+ else
180
+ raise NotImplementedError
181
+ end
182
+ end
183
+
184
+ def get_type_id_for_type_name(name)
185
+ if (name == "tf")
186
+ result = Types::BOOL
187
+ elsif (name == "i8")
188
+ result = Types::BYTE
189
+ elsif (name == "i16")
190
+ result = Types::I16
191
+ elsif (name == "i32")
192
+ result = Types::I32
193
+ elsif (name == "i64")
194
+ result = Types::I64
195
+ elsif (name == "dbl")
196
+ result = Types::DOUBLE
197
+ elsif (name == "str")
198
+ result = Types::STRING
199
+ elsif (name == "rec")
200
+ result = Types::STRUCT
201
+ elsif (name == "map")
202
+ result = Types::MAP
203
+ elsif (name == "set")
204
+ result = Types::SET
205
+ elsif (name == "lst")
206
+ result = Types::LIST
207
+ else
208
+ result = Types::STOP
209
+ end
210
+ if (result == Types::STOP)
211
+ raise NotImplementedError
212
+ end
213
+ return result
214
+ end
215
+
216
+ # Static helper functions
217
+
218
+ # Read 1 character from the trans and verify that it is the expected character ch.
219
+ # Throw a protocol exception if it is not.
220
+ def self.read_syntax_char(reader, ch)
221
+ ch2 = reader.read
222
+ if (ch2 != ch)
223
+ raise ProtocolException.new(ProtocolException::INVALID_DATA, "Expected \'#{ch}\' got \'#{ch2}\'.")
224
+ end
225
+ end
226
+
227
+ # Return true if the character ch is in [-+0-9.Ee]; false otherwise
228
+ def is_json_numeric(ch)
229
+ case ch
230
+ when '+', '-', '.', '0' .. '9', 'E', "e"
231
+ return true
232
+ else
233
+ return false
234
+ end
235
+ end
236
+
237
+ def push_context(context)
238
+ @contexts.push(@context)
239
+ @context = context
240
+ end
241
+
242
+ def pop_context
243
+ @context = @contexts.pop
244
+ end
245
+
246
+ # Write the character ch as a JSON escape sequence ("\u00xx")
247
+ def write_json_escape_char(ch)
248
+ trans.write('\\u')
249
+ ch_value = ch[0]
250
+ if (ch_value.kind_of? String)
251
+ ch_value = ch.bytes.first
252
+ end
253
+ trans.write(ch_value.to_s(16).rjust(4,'0'))
254
+ end
255
+
256
+ # Write the character ch as part of a JSON string, escaping as appropriate.
257
+ def write_json_char(ch)
258
+ # This table describes the handling for the first 0x30 characters
259
+ # 0 : escape using "\u00xx" notation
260
+ # 1 : just output index
261
+ # <other> : escape using "\<other>" notation
262
+ kJSONCharTable = [
263
+ # 0 1 2 3 4 5 6 7 8 9 A B C D E F
264
+ 0, 0, 0, 0, 0, 0, 0, 0,'b','t','n', 0,'f','r', 0, 0, # 0
265
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 1
266
+ 1, 1,'"', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, # 2
267
+ ]
268
+
269
+ ch_value = ch[0]
270
+ if (ch_value.kind_of? String)
271
+ ch_value = ch.bytes.first
272
+ end
273
+ if (ch_value >= 0x30)
274
+ if (ch == @@kJSONBackslash) # Only special character >= 0x30 is '\'
275
+ trans.write(@@kJSONBackslash)
276
+ trans.write(@@kJSONBackslash)
277
+ else
278
+ trans.write(ch)
279
+ end
280
+ else
281
+ outCh = kJSONCharTable[ch_value];
282
+ # Check if regular character, backslash escaped, or JSON escaped
283
+ if outCh.kind_of? String
284
+ trans.write(@@kJSONBackslash)
285
+ trans.write(outCh)
286
+ elsif outCh == 1
287
+ trans.write(ch)
288
+ else
289
+ write_json_escape_char(ch)
290
+ end
291
+ end
292
+ end
293
+
294
+ # Write out the contents of the string str as a JSON string, escaping characters as appropriate.
295
+ def write_json_string(str)
296
+ @context.write(trans)
297
+ trans.write(@@kJSONStringDelimiter)
298
+ str.split('').each do |ch|
299
+ write_json_char(ch)
300
+ end
301
+ trans.write(@@kJSONStringDelimiter)
302
+ end
303
+
304
+ # Write out the contents of the string as JSON string, base64-encoding
305
+ # the string's contents, and escaping as appropriate
306
+ def write_json_base64(str)
307
+ @context.write(trans)
308
+ trans.write(@@kJSONStringDelimiter)
309
+ write_json_string([str].pack("m"))
310
+ trans.write(@@kJSONStringDelimiter)
311
+ end
312
+
313
+ # Convert the given integer type to a JSON number, or a string
314
+ # if the context requires it (eg: key in a map pair).
315
+ def write_json_integer(num)
316
+ @context.write(trans)
317
+ escapeNum = @context.escapeNum
318
+ if (escapeNum)
319
+ trans.write(@@kJSONStringDelimiter)
320
+ end
321
+ trans.write(num.to_s);
322
+ if (escapeNum)
323
+ trans.write(@@kJSONStringDelimiter)
324
+ end
325
+ end
326
+
327
+ # Convert the given double to a JSON string, which is either the number,
328
+ # "NaN" or "Infinity" or "-Infinity".
329
+ def write_json_double(num)
330
+ @context.write(trans)
331
+ # Normalize output of boost::lexical_cast for NaNs and Infinities
332
+ special = false;
333
+ if (num.nan?)
334
+ special = true;
335
+ val = @@kThriftNan;
336
+ elsif (num.infinite?)
337
+ special = true;
338
+ val = @@kThriftInfinity;
339
+ if (num < 0.0)
340
+ val = @@kThriftNegativeInfinity;
341
+ end
342
+ else
343
+ val = num.to_s
344
+ end
345
+
346
+ escapeNum = special || @context.escapeNum
347
+ if (escapeNum)
348
+ trans.write(@@kJSONStringDelimiter)
349
+ end
350
+ trans.write(val)
351
+ if (escapeNum)
352
+ trans.write(@@kJSONStringDelimiter)
353
+ end
354
+ end
355
+
356
+ def write_json_object_start
357
+ @context.write(trans)
358
+ trans.write(@@kJSONObjectStart)
359
+ push_context(JSONPairContext.new);
360
+ end
361
+
362
+ def write_json_object_end
363
+ pop_context
364
+ trans.write(@@kJSONObjectEnd)
365
+ end
366
+
367
+ def write_json_array_start
368
+ @context.write(trans)
369
+ trans.write(@@kJSONArrayStart)
370
+ push_context(JSONListContext.new);
371
+ end
372
+
373
+ def write_json_array_end
374
+ pop_context
375
+ trans.write(@@kJSONArrayEnd)
376
+ end
377
+
378
+ def write_message_begin(name, type, seqid)
379
+ write_json_array_start
380
+ write_json_integer(@@kThriftVersion1)
381
+ write_json_string(name)
382
+ write_json_integer(type)
383
+ write_json_integer(seqid)
384
+ end
385
+
386
+ def write_message_end
387
+ write_json_array_end
388
+ end
389
+
390
+ def write_struct_begin(name)
391
+ write_json_object_start
392
+ end
393
+
394
+ def write_struct_end
395
+ write_json_object_end
396
+ end
397
+
398
+ def write_field_begin(name, type, id)
399
+ write_json_integer(id)
400
+ write_json_object_start
401
+ write_json_string(get_type_name_for_type_id(type))
402
+ end
403
+
404
+ def write_field_end
405
+ write_json_object_end
406
+ end
407
+
408
+ def write_field_stop; nil; end
409
+
410
+ def write_map_begin(ktype, vtype, size)
411
+ write_json_array_start
412
+ write_json_string(get_type_name_for_type_id(ktype))
413
+ write_json_string(get_type_name_for_type_id(vtype))
414
+ write_json_integer(size)
415
+ write_json_object_start
416
+ end
417
+
418
+ def write_map_end
419
+ write_json_object_end
420
+ write_json_array_end
421
+ end
422
+
423
+ def write_list_begin(etype, size)
424
+ write_json_array_start
425
+ write_json_string(get_type_name_for_type_id(etype))
426
+ write_json_integer(size)
427
+ end
428
+
429
+ def write_list_end
430
+ write_json_array_end
431
+ end
432
+
433
+ def write_set_begin(etype, size)
434
+ write_json_array_start
435
+ write_json_string(get_type_name_for_type_id(etype))
436
+ write_json_integer(size)
437
+ end
438
+
439
+ def write_set_end
440
+ write_json_array_end
441
+ end
442
+
443
+ def write_bool(bool)
444
+ write_json_integer(bool ? 1 : 0)
445
+ end
446
+
447
+ def write_byte(byte)
448
+ write_json_integer(byte)
449
+ end
450
+
451
+ def write_i16(i16)
452
+ write_json_integer(i16)
453
+ end
454
+
455
+ def write_i32(i32)
456
+ write_json_integer(i32)
457
+ end
458
+
459
+ def write_i64(i64)
460
+ write_json_integer(i64)
461
+ end
462
+
463
+ def write_double(dub)
464
+ write_json_double(dub)
465
+ end
466
+
467
+ def write_string(str)
468
+ write_json_string(str)
469
+ end
470
+
471
+ def write_binary(str)
472
+ write_json_base64(str)
473
+ end
474
+
475
+ ##
476
+ # Reading functions
477
+ ##
478
+
479
+ # Reads 1 byte and verifies that it matches ch.
480
+ def read_json_syntax_char(ch)
481
+ JsonProtocol::read_syntax_char(@reader, ch)
482
+ end
483
+
484
+ # Decodes the four hex parts of a JSON escaped string character and returns
485
+ # the character via out. The first two characters must be "00".
486
+ def read_json_escape_char
487
+ read_json_syntax_char('0')
488
+ read_json_syntax_char('0')
489
+ str = @reader.read
490
+ str += @reader.read
491
+ str.hex.chr
492
+ end
493
+
494
+ # Decodes a JSON string, including unescaping, and returns the string via str
495
+ def read_json_string(skipContext = false)
496
+ # This string's characters must match up with the elements in escape_char_vals.
497
+ # I don't have '/' on this list even though it appears on www.json.org --
498
+ # it is not in the RFC
499
+ escape_chars = "\"\\bfnrt"
500
+
501
+ # The elements of this array must match up with the sequence of characters in
502
+ # escape_chars
503
+ escape_char_vals = [
504
+ '"', '\\', '\b', '\f', '\n', '\r', '\t',
505
+ ]
506
+
507
+ if !skipContext
508
+ @context.read(@reader)
509
+ end
510
+ read_json_syntax_char(@@kJSONStringDelimiter)
511
+ ch = ""
512
+ str = ""
513
+ while (true)
514
+ ch = @reader.read
515
+ if (ch == @@kJSONStringDelimiter)
516
+ break
517
+ end
518
+ if (ch == @@kJSONBackslash)
519
+ ch = @reader.read
520
+ if (ch == 'u')
521
+ ch = read_json_escape_char
522
+ else
523
+ pos = escape_chars.index(ch);
524
+ if (pos.nil?) # not found
525
+ raise ProtocolException.new(ProtocolException::INVALID_DATA, "Expected control char, got \'#{ch}\'.")
526
+ end
527
+ ch = escape_char_vals[pos]
528
+ end
529
+ end
530
+ str += ch
531
+ end
532
+ return str
533
+ end
534
+
535
+ # Reads a block of base64 characters, decoding it, and returns via str
536
+ def read_json_base64
537
+ read_json_string.unpack("m")[0]
538
+ end
539
+
540
+ # Reads a sequence of characters, stopping at the first one that is not
541
+ # a valid JSON numeric character.
542
+ def read_json_numeric_chars
543
+ str = ""
544
+ while (true)
545
+ ch = @reader.peek
546
+ if (!is_json_numeric(ch))
547
+ break;
548
+ end
549
+ ch = @reader.read
550
+ str += ch
551
+ end
552
+ return str
553
+ end
554
+
555
+ # Reads a sequence of characters and assembles them into a number,
556
+ # returning them via num
557
+ def read_json_integer
558
+ @context.read(@reader)
559
+ if (@context.escapeNum)
560
+ read_json_syntax_char(@@kJSONStringDelimiter)
561
+ end
562
+ str = read_json_numeric_chars
563
+
564
+ begin
565
+ num = Integer(str);
566
+ rescue
567
+ raise ProtocolException.new(ProtocolException::INVALID_DATA, "Expected numeric value; got \"#{str}\"")
568
+ end
569
+
570
+ if (@context.escapeNum)
571
+ read_json_syntax_char(@@kJSONStringDelimiter)
572
+ end
573
+
574
+ return num
575
+ end
576
+
577
+ # Reads a JSON number or string and interprets it as a double.
578
+ def read_json_double
579
+ @context.read(@reader)
580
+ num = 0
581
+ if (@reader.peek == @@kJSONStringDelimiter)
582
+ str = read_json_string(true)
583
+ # Check for NaN, Infinity and -Infinity
584
+ if (str == @@kThriftNan)
585
+ num = (+1.0/0.0)/(+1.0/0.0)
586
+ elsif (str == @@kThriftInfinity)
587
+ num = +1.0/0.0
588
+ elsif (str == @@kThriftNegativeInfinity)
589
+ num = -1.0/0.0
590
+ else
591
+ if (!@context.escapeNum)
592
+ # Raise exception -- we should not be in a string in this case
593
+ raise ProtocolException.new(ProtocolException::INVALID_DATA, "Numeric data unexpectedly quoted")
594
+ end
595
+ begin
596
+ num = Float(str)
597
+ rescue
598
+ raise ProtocolException.new(ProtocolException::INVALID_DATA, "Expected numeric value; got \"#{str}\"")
599
+ end
600
+ end
601
+ else
602
+ if (@context.escapeNum)
603
+ # This will throw - we should have had a quote if escapeNum == true
604
+ read_json_syntax_char(@@kJSONStringDelimiter)
605
+ end
606
+ str = read_json_numeric_chars
607
+ begin
608
+ num = Float(str)
609
+ rescue
610
+ raise ProtocolException.new(ProtocolException::INVALID_DATA, "Expected numeric value; got \"#{str}\"")
611
+ end
612
+ end
613
+ return num
614
+ end
615
+
616
+ def read_json_object_start
617
+ @context.read(@reader)
618
+ read_json_syntax_char(@@kJSONObjectStart)
619
+ push_context(JSONPairContext.new)
620
+ nil
621
+ end
622
+
623
+ def read_json_object_end
624
+ read_json_syntax_char(@@kJSONObjectEnd)
625
+ pop_context
626
+ nil
627
+ end
628
+
629
+ def read_json_array_start
630
+ @context.read(@reader)
631
+ read_json_syntax_char(@@kJSONArrayStart)
632
+ push_context(JSONListContext.new)
633
+ nil
634
+ end
635
+
636
+ def read_json_array_end
637
+ read_json_syntax_char(@@kJSONArrayEnd)
638
+ pop_context
639
+ nil
640
+ end
641
+
642
+ def read_message_begin
643
+ read_json_array_start
644
+ version = read_json_integer
645
+ if (version != @@kThriftVersion1)
646
+ raise ProtocolException.new(ProtocolException::BAD_VERSION, 'Message contained bad version.')
647
+ end
648
+ name = read_json_string
649
+ message_type = read_json_integer
650
+ seqid = read_json_integer
651
+ [name, message_type, seqid]
652
+ end
653
+
654
+ def read_message_end
655
+ read_json_array_end
656
+ nil
657
+ end
658
+
659
+ def read_struct_begin
660
+ read_json_object_start
661
+ nil
662
+ end
663
+
664
+ def read_struct_end
665
+ read_json_object_end
666
+ nil
667
+ end
668
+
669
+ def read_field_begin
670
+ # Check if we hit the end of the list
671
+ ch = @reader.peek
672
+ if (ch == @@kJSONObjectEnd)
673
+ field_type = Types::STOP
674
+ else
675
+ field_id = read_json_integer
676
+ read_json_object_start
677
+ field_type = get_type_id_for_type_name(read_json_string)
678
+ end
679
+ [nil, field_type, field_id]
680
+ end
681
+
682
+ def read_field_end
683
+ read_json_object_end
684
+ end
685
+
686
+ def read_map_begin
687
+ read_json_array_start
688
+ key_type = get_type_id_for_type_name(read_json_string)
689
+ val_type = get_type_id_for_type_name(read_json_string)
690
+ size = read_json_integer
691
+ read_json_object_start
692
+ [key_type, val_type, size]
693
+ end
694
+
695
+ def read_map_end
696
+ read_json_object_end
697
+ read_json_array_end
698
+ end
699
+
700
+ def read_list_begin
701
+ read_json_array_start
702
+ [get_type_id_for_type_name(read_json_string), read_json_integer]
703
+ end
704
+
705
+ def read_list_end
706
+ read_json_array_end
707
+ end
708
+
709
+ def read_set_begin
710
+ read_json_array_start
711
+ end
712
+
713
+ def read_set_end
714
+ read_json_array_end
715
+ end
716
+
717
+ def read_bool
718
+ byte = read_byte
719
+ byte != 0
720
+ end
721
+
722
+ def read_byte
723
+ read_json_integer
724
+ end
725
+
726
+ def read_i16
727
+ read_json_integer
728
+ end
729
+
730
+ def read_i32
731
+ read_json_integer
732
+ end
733
+
734
+ def read_i64
735
+ read_json_integer
736
+ end
737
+
738
+ def read_double
739
+ read_json_double
740
+ end
741
+
742
+ def read_string
743
+ read_json_string
744
+ end
745
+
746
+ def read_binary
747
+ read_json_base64
748
+ end
749
+ end
750
+
751
+ class JsonProtocolFactory < BaseProtocolFactory
752
+ def get_protocol(trans)
753
+ return Thrift::JsonProtocol.new(trans)
754
+ end
755
+ end
756
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: thrift-json
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.8.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Apache Thrift
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-23 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: thrift
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '0.8'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '0.8'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rdoc
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '3.12'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '3.12'
46
+ - !ruby/object:Gem::Dependency
47
+ name: bundler
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: jeweler
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 1.8.4
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 1.8.4
78
+ description: The missing JsonProtocol from Thrift
79
+ email:
80
+ executables: []
81
+ extensions: []
82
+ extra_rdoc_files:
83
+ - README.md
84
+ files:
85
+ - lib/thrift-json.rb
86
+ - lib/thrift/json_protocol.rb
87
+ - README.md
88
+ homepage: http://github.com/elseano/thrift-rb-json
89
+ licenses:
90
+ - Apache License, Version 2.0
91
+ post_install_message:
92
+ rdoc_options: []
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ! '>='
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ segments:
102
+ - 0
103
+ hash: 3766590854295571078
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubyforge_project:
112
+ rubygems_version: 1.8.23
113
+ signing_key:
114
+ specification_version: 3
115
+ summary: The missing JsonProtocol from Thrift
116
+ test_files: []