Class: Sqreen::SafeJSON
- Inherits:
-
Object
- Object
- Sqreen::SafeJSON
- Defined in:
- lib/sqreen/safe_json.rb
Overview
Safely dump datastructure in json (more resilient to encoding errors)
Class Method Summary collapse
- .dump(data) ⇒ Object
- .enforce_encoding(str) ⇒ Object
- .rencode_array(array, max_depth) ⇒ Object
- .rencode_payload(obj, max_depth = 20) ⇒ Object
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 |