ruby - How to truncate data in a hash so that the resulting JSON isn't longer than n bytes? -
i have hash looks this:
{ :a => "some string", :b => "another string", :c => "yet string" }
i wan't call to_json
on eventually, resulting json-string cannot longer n
bytes.
if string big, first :c
should truncated first. if that's not enough, :b
should truncated. :a
. strings can contain multi-byte characters german umlauts , ruby version 1.8.7. (the umlauts first take 2 bytes, json 5 bytes long.)
what wrote loop converts hash to_json , checks length. if less or equal n
it's returned, otherwise concat values of :a
+ :b
+ :c
, shorten half. if new hash big(small), shorten(extend) 1/4th, 1/8th, 1/16th of original string. length of hash.as_json == n
.
it feels hackish , although tests check out i'm not sure that's stable.
does have suggestion how solve properly?
how about:
# encoding:utf-8 require 'rubygems' require 'json' def constrained_json(limit, a, b, c) output, size, hash = nil, 0, { :a => a, :b => b, :c => c} [:c, :b, :a, :a].each |key| output = hash.to_json size = output.bytesize break if size <= limit # on 1.9: # hash[key] = hash[key][0...(limit - size)] # on 1.8.7 hash[key] = hash[key].unpack("u*")[0...(limit - size)].pack("u*") end raise "size exceeds limit after truncation" if size > limit output end 38.downto(21) |length| puts "# #{constrained_json(length, "qué te", "parece", "eh?")}" end # {"a":"qué te","b":"parece","c":"eh?"} # {"a":"qué te","b":"parece","c":"eh"} # {"a":"qué te","b":"parece","c":"e"} # {"a":"qué te","b":"parece","c":""} # {"a":"qué te","b":"parec","c":""} # {"a":"qué te","b":"pare","c":""} # ... # {"a":"","b":"","c":""} # test.rb:14:in `constrained_json': size exceeds limit after truncation (runtimeerror)
Comments
Post a Comment