Module: Causalontology::Jcs
- Defined in:
- lib/causalontology/jcs.rb
Constant Summary collapse
- ESCAPES =
The two-character escapes of RFC 8785 section 3.2.2.2.
{ '"' => '\"', "\\" => "\\\\", "\b" => "\\b", "\t" => "\\t", "\n" => "\\n", "\f" => "\\f", "\r" => "\\r", }.freeze
Class Method Summary collapse
-
.encode(value) ⇒ Object
The canonical serialization of a parsed JSON value (nil, true/false, Integer, Float, String, Array, or Hash with String keys).
-
.number(n) ⇒ Object
A canonical JSON number: integers verbatim; integer-valued floats below 1e21 printed as integers; other floats in shortest round-trip form with the exponent normalized to ES6 style ("1e-7", "1e+21").
-
.string(s) ⇒ Object
A JSON string literal with minimal escaping: the seven two-character escapes, \u00xx for remaining control characters, everything else (including multibyte text) passed through as UTF-8.
Class Method Details
.encode(value) ⇒ Object
The canonical serialization of a parsed JSON value (nil, true/false, Integer, Float, String, Array, or Hash with String keys).
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/causalontology/jcs.rb', line 73 def encode(value) case value when nil "null" when true "true" when false "false" when Integer, Float number(value) when String string(value) when Array "[" + value.map { |v| encode(v) }.join(",") + "]" when Hash items = value.keys.sort_by(&:codepoints) "{" + items.map { |k| string(k) + ":" + encode(value[k]) }.join(",") + "}" else raise TypeError, "cannot canonicalize #{value.class}" end end |
.number(n) ⇒ Object
A canonical JSON number: integers verbatim; integer-valued floats below 1e21 printed as integers; other floats in shortest round-trip form with the exponent normalized to ES6 style ("1e-7", "1e+21").
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/causalontology/jcs.rb', line 54 def number(n) return n.to_s if n.is_a?(Integer) raise ArgumentError, "NaN and Infinity are not permitted (RFC 8785)" unless n.finite? return "0" if n == 0 return n.to_i.to_s if n == n.truncate && n.abs < 1e21 r = n.to_s # shortest round-trip decimal if r.include?("e") mant, exp = r.split("e") mant = mant.sub(/\.0\z/, "") # Ruby prints "1.0e-07"; ES6 prints "1e-7" sign = exp.start_with?("-") ? "-" : "+" digits = exp.sub(/\A[+-]/, "").sub(/\A0+/, "") digits = "0" if digits.empty? r = mant + "e" + sign + digits end r end |
.string(s) ⇒ Object
A JSON string literal with minimal escaping: the seven two-character escapes, \u00xx for remaining control characters, everything else (including multibyte text) passed through as UTF-8.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/causalontology/jcs.rb', line 36 def string(s) parts = +'"' s.each_char do |ch| if ESCAPES.key?(ch) parts << ESCAPES[ch] elsif ch.ord < 0x20 parts << format("\\u%04x", ch.ord) else parts << ch end end parts << '"' parts end |