Class: Sqreen::SafeJSON

Inherits:
Object
  • Object
show all
Defined in:
lib/sqreen/safe_json.rb

Overview

Safely dump datastructure in json (more resilient to encoding errors)

Class Method Summary collapse

Class Method Details

.dump(data) ⇒ Object



13
14
15
16
17
18
# File 'lib/sqreen/safe_json.rb', line 13

def self.dump(data)
  JSON.generate(data)
rescue JSON::GeneratorError, Encoding::UndefinedConversionError
  Sqreen.log.debug('Payload could not be encoded enforcing recode')
  JSON.generate(rencode_payload(data))
end

.enforce_encoding(str) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/sqreen/safe_json.rb', line 47

def self.enforce_encoding(str)
  return str unless str.is_a?(String)
  return str if str.ascii_only?
  encoded8bit = str.encoding.name == 'ASCII-8BIT'
  return str if !encoded8bit && str.valid_encoding?
  r = str.chars.map do |v|
    if !v.valid_encoding? || (encoded8bit && !v.ascii_only?)
      v.bytes.map { |c| "\\x#{c.to_s(16).upcase}" }.join
    else
      v
    end
  end.join
  "SqBytes[#{r}]"
end

.rencode_array(array, max_depth) ⇒ Object



42
43
44
45
# File 'lib/sqreen/safe_json.rb', line 42

def self.rencode_array(array, max_depth)
  array.map! { |e| rencode_payload(e, max_depth - 1) }
  array
end

.rencode_payload(obj, max_depth = 20) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/sqreen/safe_json.rb', line 20

def self.rencode_payload(obj, max_depth = 20)
  max_depth -= 1
  return obj if max_depth < 0
  return rencode_array(obj, max_depth) if obj.is_a?(Array)
  return enforce_encoding(obj) unless obj.is_a?(Hash)
  nobj = {}
  obj.each do |k, v|
    safe_k = rencode_payload(k, max_depth)
    nobj[safe_k] = case v
                   when Array
                     rencode_array(v, max_depth)
                   when Hash
                     rencode_payload(v, max_depth)
                   when String
                     enforce_encoding(v)
                   else # for example integers
                     v
                   end
  end
  nobj
end