source: EcnlProtoTool/trunk/mrbgems/mruby-iijson/mrblib/json.rb@ 439

Last change on this file since 439 was 439, checked in by coas-nagasima, 4 years ago

mrubyを2.1.1に更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby
File size: 3.1 KB
Line 
1module JSON
2 def self.dump(object, io=nil, limit=nil)
3 state = {}
4 state[:max_nesting] = limit if limit
5 begin
6 js = JSON.generate(object, nil, state)
7 rescue JSON::NestingError
8 raise ArgumentError, "exceeded depth limit"
9 end
10 if io
11 io.write js
12 io
13 else
14 js
15 end
16 end
17
18 def self.generate(obj, options=nil, state=nil)
19 options = (options || {}).to_h unless options.is_a? Hash
20 options[:pretty_print] ||= false
21 options[:indent_with] ||= 2
22 state = (state || {}).to_h unless state.is_a? Hash
23 state[:max_nesting] ||= 100
24 state[:nesting] = 0
25 self.generate0(obj, options, state)
26 end
27
28 def self.generate0(obj, options, state)
29 if state[:nesting] >= state[:max_nesting]
30 raise JSON::NestingError, "nesting of #{state[:nesting]} is too deep"
31 end
32
33 pretty = options[:pretty_print]
34
35 if pretty
36 indent = options[:indent_with].class == Fixnum ? " " * options[:indent_with] : options[:indent_with]
37 else
38 indent = ""
39 end
40
41 nl = pretty ? "\n" : ""
42
43 if obj == false
44 return "false"
45
46 elsif obj == nil
47 return "null"
48
49 elsif obj == true
50 return "true"
51
52 elsif obj.is_a? Hash
53 members = []
54 state[:nesting] += 1
55 obj.each { |k, v|
56 members << JSON.generate0(k, options, state) + ":" + (pretty ? " " : "") + JSON.generate0(v, options, state)
57 }
58 if pretty
59 members.map! { |k| (indent * state[:nesting]) + "#{k}" }.join("_")
60 end
61 state[:nesting] -= 1
62 return "{" + nl + members.join("," + nl) + nl + (indent * state[:nesting]) + "}"
63
64 elsif obj.is_a? Array
65 state[:nesting] += 1
66 members = obj.map { |v| JSON.generate0(v, options, state) }
67 if pretty
68 members.map! { |k| (indent * state[:nesting]) + "#{k}" }.join("_")
69 end
70 state[:nesting] -= 1
71 return "[" + nl + members.join("," + nl) + nl + (indent * state[:nesting]) + "]"
72
73 elsif obj.is_a? Fixnum
74 return obj.to_s
75
76 elsif obj.is_a? Float
77 if obj.infinite? or obj.nan?
78 raise GeneratorError, "#{obj.to_s} not allowed in JSON"
79 end
80 sprintf "%.17g", obj
81
82 else
83 a = []
84 obj.to_s.each_char { |ch|
85 a << if ch < "\x20"
86 case ch
87 when "\x08"
88 "\\b"
89 when "\x0c"
90 "\\f"
91 when "\x0a"
92 "\\n"
93 when "\x0d"
94 "\\r"
95 when "\x09"
96 "\\t"
97 else
98 raise GeneratorError, "cannot convert #{ch.inspect} to JSON"
99 end
100 elsif ch == '"'
101 '\\"'
102 elsif ch == '\\'
103 "\\\\"
104 else
105 ch
106 end
107 }
108 return '"' + a.join + '"'
109 end
110 end
111
112 def self.load(source) # TODO: proc, options
113 source = source.read unless source.is_a? String
114 JSON.parse source
115 end
116
117 class JSONError < StandardError; end
118 class GeneratorError < JSONError; end
119 class ParserError < JSONError; end
120 class NestingError < ParserError; end
121end
122
123unless Float.method_defined? :nan?
124 class Float
125 def nan?
126 not (self == self)
127 end
128 end
129end
Note: See TracBrowser for help on using the repository browser.