d15ceb76c3ac69664640fcde21e65c3c3447ba58
1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # Dynamic interface to read Json strings.
19 # `String::to_json_value` returns a `JsonValue` which can be queried
20 # to get the underlying Json data. It can also be used as any Json types.
27 var value
: nullable Object
31 # assert "null".to_json_value.is_null
32 # assert not "123".to_json_value.is_null
33 fun is_null
: Bool do return value
== null
35 # Is this value an integer?
37 # assert "123".to_json_value.is_int
38 # assert not "1.23".to_json_value.is_int
39 # assert not "\"str\"".to_json_value.is_int
40 fun is_int
: Bool do return value
isa Int
42 # Get this value as a `Int`
44 # require: `self.is_int`
46 # assert "-10".to_json_value.to_i == -10
47 # assert "123".to_json_value.to_i == 123
48 fun to_i
: Int do return value
.as(Int)
50 # Is this value a float?
52 # assert "0.0".to_json_value.is_float
53 # assert "123.456".to_json_value.is_float
54 # assert not "123".to_json_value.is_float
55 fun is_float
: Bool do return value
isa Float
57 # Get this value as a `Float`
59 # require: `self.is_float`
61 # assert "0.0".to_json_value.to_f == 0.0
62 # assert "123.456".to_json_value.to_f == 123.456
63 fun to_f
: Float do return value
.as(Float)
65 # Is the value numeric?
67 # assert "1.234".to_json_value.is_numeric
68 # assert "1234".to_json_value.is_numeric
69 # assert not "\"str\"".to_json_value.is_numeric
70 # assert not "1.2.3.4".to_json_value.is_numeric
71 fun is_numeric
: Bool do return is_int
or is_float
73 # Get this value as a `Numeric`
75 # require: `self.is_numeric`
77 # assert "1.234".to_json_value.to_numeric = 1.234
78 # assert "1234".to_json_value.to_numeric = 1234
79 fun to_numeric
: Numeric
81 if is_int
then return to_i
85 # Is this value a boolean?
87 # assert "true".to_json_value.is_bool
88 # assert "false".to_json_value.is_bool
89 fun is_bool
: Bool do return value
isa Bool
91 # Get this value as a `Bool`
93 # require: `self.is_bool`
95 # assert "true".to_json_value.to_bool
96 # assert not "false".to_json_value.to_bool
97 fun to_bool
: Bool do return value
.as(Bool)
99 # Is this value a string?
101 # assert "\"str\"".to_json_value.is_string
102 # assert not "123".to_json_value.is_string
103 fun is_string
: Bool do return value
isa String
105 # Get this value as a `String`
107 # If value is null, return "null", otherwise returns `value.to_s`. It is practical
108 # on most types, except maps which does not have a custom `to_s`.
110 # assert "\"str\"".to_json_value.to_s == "str"
111 # assert "123".to_json_value.to_s == "123"
112 # assert "true".to_json_value.to_s == "true"
113 # assert "[1, 2, 3]".to_json_value.to_s == "123"
114 redef fun to_s
: String
116 if value
== null then return "null"
122 # Is this value a Json object (a map)?
124 # assert """{"a": 123}""".to_json_value.is_map
125 # assert not "123".to_json_value.is_map
126 fun is_map
: Bool do return value
isa MapRead[String, nullable Object]
128 # Get this value as a `Map[String, JsonValue]`
130 # require: `self.is_map`
131 fun to_map
: Map[String, JsonValue] do
133 assert value
isa MapRead[String, nullable Object]
135 var map
= new HashMap[String, JsonValue]
136 for k
, v
in value
do map
[k
] = new JsonValue(v
)
142 # Is this value an array?
144 # assert "[]".to_json_value.is_array
145 # assert "[1, 2, 3, 4, 5]".to_json_value.is_array
146 # assert "[null, true, false, 0.0, 1, \"str\"]".to_json_value.is_array
147 # assert """["a", "b", "c"]""".to_json_value.is_array
148 fun is_array
: Bool do return value
isa SequenceRead[nullable Object]
150 # Get this value as an `Array[JsonValue]`
152 # require: `self.is_array`
154 # assert """["a", "b", "c"]""".to_json_value.to_a.join(", ") == "a, b, c"
155 fun to_a
: Array[JsonValue]
158 assert value
isa SequenceRead[nullable Object]
160 var a
= new Array[JsonValue]
161 for e
in value
do a
.add
(new JsonValue(e
))
167 # Is this value an error?
169 # assert "[]".to_json_value[0].is_error
170 # assert "[".to_json_value.is_error
171 # assert not "[]".to_json_value.is_error
172 fun is_error
: Bool do return value
isa Error
174 # Get this value as a `Error`.
176 # require: `self.is_error`
177 fun to_error
: Error do return value
.as(Error)
181 # Is this value a parse error?
183 # assert "[".to_json_value.is_parse_error
184 # assert not "[]".to_json_value.is_parse_error
185 fun is_parse_error
: Bool do return value
isa JsonParseError
187 # Get this value as a `JsonParseError`.
189 # require: `self.is_parse_error`
190 fun to_parse_error
: JsonParseError do return value
.as(JsonParseError)
194 # Iterator over the values of the array `self`
196 # require: `self.is_array`
198 # var a = new Array[String]
199 # for e in """["a", "b", "c"]""".to_json_value do a.add(e.to_s)
203 fun iterator
: Iterator[JsonValue] do return to_a
.iterator
205 # Get value at index `key` on the array or map `self`
207 # require: `self.is_array or self.is_map`
208 # require: `self.is_array implies key isa Int`
210 # assert """{"a": 123}""".to_json_value["a"].to_i == 123
211 # assert """{"123": "a"}""".to_json_value[123].to_s == "a"
212 # assert """{"John Smith": 1980}""".to_json_value[["John ", "Smith"]].to_i == 1980
213 # assert """{"a": 123}""".to_json_value["b"].is_error
215 # assert """["a", "b", "c"]""".to_json_value[0].to_s == "a"
216 # assert """["a", "b", "c"]""".to_json_value[3].is_error
217 fun [](key
: Object): JsonValue do
219 var result
: nullable Object
222 else if value
isa MapRead[String, nullable Object] then
224 if value
.has_key
(key
) then
227 result
= new JsonKeyError("Key `{key}` not found.", self, key
)
229 else if value
isa SequenceRead[nullable Object] then
231 if key
< value
.length
and key
>= 0 then
234 result
= new JsonKeyError("Index `{key}` out of bounds.",
238 result
= new JsonKeyError("Invalid key type. Expecting `Int`. Got `{key.class_name}`.",
242 result
= new JsonKeyError("Invalid `[]` access on a `{json_type}` JsonValue.",
245 return new JsonValue(result
)
248 # Advanced query to get a value within the map `self` or it's children.
250 # A query is composed of the keys to each map seperated by '.'.
252 # require: `self.is_map`
254 # assert """{"a": {"t": true, "f": false}}""".to_json_value.get("a").is_map
255 # assert """{"a": {"t": true, "f": false}}""".to_json_value.get("a.t").to_bool
256 # assert not """{"a": {"t": true, "f": false}}""".to_json_value.get("a.f").to_bool
257 # assert """{"a": {"t": true, "f": false}}""".to_json_value.get("a.t.t").is_error
258 # assert """{"a": {"b": {"c": {"d": 123}}}}""".to_json_value.get("a.b.c.d").to_i == 123
259 # assert """{"a": {"b": {"c": {"d": 123}}}}""".to_json_value.get("a.z.c.d").is_error
260 fun get
(query
: String): JsonValue do
261 var keys
= query
.split
(".")
263 if is_error
then return self
264 for i
in [0..keys
.length
[ do
266 if value
isa MapRead[String, nullable Object] then
267 if value
.has_key
(key
) then
270 var sub_query
= sub_query_to_s
(keys
, i
)
271 var e
= new JsonKeyError("Key `{key}` not found.",
273 return new JsonValue(e
)
276 var sub_query
= sub_query_to_s
(keys
, i
)
277 var val_type
= (new JsonValue(value
)).json_type
278 var e
= new JsonKeyError("Value at `{sub_query}` is not a map. Got type `{val_type}`",
280 return new JsonValue(e
)
283 return new JsonValue(value
)
286 # Concatenate all keys up to `last` for debugging purposes.
288 # Note: This method deletes elements in `keys`.
289 private fun sub_query_to_s
(keys
: Array[String], last
: Int): String do
291 for j
in [last
..keys
.length
[ do keys
.pop
292 return keys
.join
(".")
295 # Return a human-readable description of the type.
297 # For debugging purpose only.
298 fun json_type
: String do
299 if is_array
then return "array"
300 if is_bool
then return "bool"
301 if is_float
then return "float"
302 if is_int
then return "int"
303 if is_null
then return "null"
304 if is_map
then return "map"
305 if is_string
then return "string"
306 if is_parse_error
then return "parse_error"
307 if is_error
then return "error"
312 # Keyed access failed.
316 # The value on which the access was requested.
317 var json_value
: JsonValue
321 # In the case of `JsonValue.get`, the sub-query that failed.
326 # Parse `self` to obtain a `JsonValue`
327 fun to_json_value
: JsonValue do
328 var value
= parse_json
329 return new JsonValue(value
)