right_support 2.6.5 → 2.6.7
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/right_support/data/hash_tools.rb +90 -0
- data/right_support.gemspec +3 -3
- metadata +5 -4
@@ -25,6 +25,8 @@ module RightSupport::Data
|
|
25
25
|
# various tools for manipulating hash-like classes.
|
26
26
|
module HashTools
|
27
27
|
|
28
|
+
HAS_JSON = require_succeeds?('json')
|
29
|
+
|
28
30
|
# Determines if given object is hashable (i.e. object responds to hash methods).
|
29
31
|
#
|
30
32
|
# === Parameters
|
@@ -257,5 +259,93 @@ module RightSupport::Data
|
|
257
259
|
target
|
258
260
|
end
|
259
261
|
|
262
|
+
class DeepSortedJsonState
|
263
|
+
|
264
|
+
# Initializer.
|
265
|
+
#
|
266
|
+
# === Parameters
|
267
|
+
# @param [TrueClass|FalseClass] pretty is true to invoke JSON::pretty_generate, false to call JSON::dump
|
268
|
+
def initialize(pretty)
|
269
|
+
# copy one of the JSON state prototypes in order to agree with recursive
|
270
|
+
# depth and other state variables.
|
271
|
+
@state = (pretty ? JSON::PRETTY_STATE_PROTOTYPE : JSON::FAST_STATE_PROTOTYPE).dup
|
272
|
+
|
273
|
+
# note that the native JSON extension *may* keep the following state
|
274
|
+
# strings as internal ruby strings in which case the state accessor (i.e.
|
275
|
+
# state.object_nl) returns a pointer to a char array instead of a String
|
276
|
+
# object. the trivial solution is to hardcode the 'pretty' strings here
|
277
|
+
# instead of trying to infer the proper string objects.
|
278
|
+
if pretty
|
279
|
+
@object_nl = "\n"
|
280
|
+
@indent = ' '
|
281
|
+
@space = ' '
|
282
|
+
else
|
283
|
+
@object_nl = ''
|
284
|
+
@indent = ''
|
285
|
+
@space = ''
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
# Generates a JSONified hash string where key/value pairs are sorted by
|
290
|
+
# the stringified key.
|
291
|
+
#
|
292
|
+
# Note that this algoritm is loosely based on the json_pure implementation
|
293
|
+
# for Hash.
|
294
|
+
#
|
295
|
+
# === Parameters
|
296
|
+
# @param [Hash] hash from which to generate JSON
|
297
|
+
#
|
298
|
+
# === Return
|
299
|
+
# @return [String] result as sorted JSONified hash
|
300
|
+
def generate(hash)
|
301
|
+
delim = ','
|
302
|
+
delim << @object_nl
|
303
|
+
result = '{'
|
304
|
+
result << @object_nl
|
305
|
+
depth = @state.depth += 1
|
306
|
+
first = true
|
307
|
+
|
308
|
+
sorted_pairs = hash.to_a.map { |key, value| [key.to_s, value] }.sort
|
309
|
+
sorted_pairs.each do |key, value|
|
310
|
+
result << delim unless first
|
311
|
+
result << @indent * depth
|
312
|
+
result << key.to_s.to_json(@state)
|
313
|
+
result << ':'
|
314
|
+
result << @space
|
315
|
+
if ::RightSupport::Data::HashTools.hashable?(value)
|
316
|
+
result << generate(value)
|
317
|
+
else
|
318
|
+
result << value.to_json(@state)
|
319
|
+
end
|
320
|
+
first = false
|
321
|
+
end
|
322
|
+
depth = @state.depth -= 1
|
323
|
+
result << @object_nl
|
324
|
+
result << @indent * depth
|
325
|
+
result << '}'
|
326
|
+
result
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
class NoJson < Exception; end
|
331
|
+
|
332
|
+
# Generates JSON from the given hash (of hashes) that is sorted by key at
|
333
|
+
# all levels. Does not handle case of hash to array of hashes, etc.
|
334
|
+
#
|
335
|
+
# === Parameters
|
336
|
+
# @param [Hash] hash from which to generate JSON
|
337
|
+
# @param [TrueClass|FalseClass] pretty is true to invoke JSON::pretty_generate, false to call JSON::dump
|
338
|
+
#
|
339
|
+
# === Return
|
340
|
+
# @return [String] result as a deep-sorted JSONized hash
|
341
|
+
def self.deep_sorted_json(hash, pretty=false)
|
342
|
+
if HAS_JSON
|
343
|
+
raise ArgumentError("'hash' was not hashable") unless hashable?(hash)
|
344
|
+
state = ::RightSupport::Data::HashTools::DeepSortedJsonState.new(pretty)
|
345
|
+
state.generate(hash)
|
346
|
+
else
|
347
|
+
raise NoJson, "JSON is unavailable"
|
348
|
+
end
|
349
|
+
end
|
260
350
|
end
|
261
351
|
end
|
data/right_support.gemspec
CHANGED
@@ -7,10 +7,10 @@ spec = Gem::Specification.new do |s|
|
|
7
7
|
s.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
|
8
8
|
|
9
9
|
s.name = 'right_support'
|
10
|
-
s.version = '2.6.
|
11
|
-
s.date = '2012-
|
10
|
+
s.version = '2.6.7'
|
11
|
+
s.date = '2012-12-13'
|
12
12
|
|
13
|
-
s.authors = ['Tony Spataro', 'Sergey Sergyenko', 'Ryan Williamson', 'Lee Kirchhoff', 'Sergey Enin', 'Alexey Karpik']
|
13
|
+
s.authors = ['Tony Spataro', 'Sergey Sergyenko', 'Ryan Williamson', 'Lee Kirchhoff', 'Sergey Enin', 'Alexey Karpik', 'Scott Messier']
|
14
14
|
s.email = 'support@rightscale.com'
|
15
15
|
s.homepage= 'https://github.com/rightscale/right_support'
|
16
16
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: right_support
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 2
|
8
8
|
- 6
|
9
|
-
-
|
10
|
-
version: 2.6.
|
9
|
+
- 7
|
10
|
+
version: 2.6.7
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Tony Spataro
|
@@ -16,11 +16,12 @@ authors:
|
|
16
16
|
- Lee Kirchhoff
|
17
17
|
- Sergey Enin
|
18
18
|
- Alexey Karpik
|
19
|
+
- Scott Messier
|
19
20
|
autorequire:
|
20
21
|
bindir: bin
|
21
22
|
cert_chain: []
|
22
23
|
|
23
|
-
date: 2012-
|
24
|
+
date: 2012-12-13 00:00:00 -08:00
|
24
25
|
default_executable:
|
25
26
|
dependencies: []
|
26
27
|
|