Как обрезать данные в хэше, чтобы результирующий JSON не превышал n байтов? - PullRequest
2 голосов
/ 21 июля 2011

У меня есть хеш, который выглядит примерно так:

{ :a => "some string", :b => "another string", :c => "yet another string" }

Я не хочу в конечном итоге вызвать to_json, но результирующая строка json не может быть длиннее n байтов.

Если строка слишком большая, то сначала нужно урезать сначала :c.Если этого недостаточно, :b следует усечь.Наконец :a.Также строки могут содержать многобайтовые символы, такие как немецкие умляуты, а версия для Ruby - 1.8.7.(Умлауты сначала занимают 2 байта, но как json они имеют длину 5 байтов.)

То, что я написал, было циклом, который преобразует хеш в _json и проверяет длину.Если оно меньше или равно n, оно возвращается, в противном случае я объединяю значения :a + :b + :c и сокращаю вдвое.Если новый хеш слишком большой (маленький), я сокращаю (расширяю) на 1/4, 1/8, 1/16 от исходной строки.Наконец я получаю длину hash.as_json == n.

Все это кажется очень хакерским, и хотя все тесты проверяют, я не уверен, что это даже стабильно.

У кого-нибудь есть хорошее предложение, как решитьэто правильно?

1 Ответ

1 голос
/ 21 июля 2011

Как насчет:

# 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 do |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 even after truncation" if size > limit
  output
end

38.downto(21) do |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 even after truncation (RuntimeError)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...