thrift-json 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: []