immutable_json/object.rs
1use crate::api::Number::{Decimal, Integer};
2use crate::api::{Number, Value};
3use crate::array::Array;
4use crate::pointer::JsonPointer;
5use imbl::HashMap;
6use imbl::hashmap::Iter;
7use imbl::shared_ptr::DefaultSharedPtr;
8use imbl_util::hashmap;
9use std::fmt::{Debug, Display, Formatter};
10use std::hash::{Hash, Hasher};
11
12/// Represents a JSON object.
13#[derive(Clone, Debug, Eq, PartialEq)]
14pub struct Object {
15 map: HashMap<String, Value>,
16}
17
18impl Default for Object {
19 fn default() -> Self {
20 Self::new()
21 }
22}
23
24impl Display for Object {
25 /**
26 Converts a JSON object to a string.
27 ```rust
28 # use immutable_json::api::Value;
29 # use immutable_json::error::Error;
30 # use std::str::FromStr;
31 # fn main() -> Result<(), Error>{
32 let data = r#"
33 {
34 "string": "string",
35 "int": 43,
36 "float": 5.8,
37 "boolean": true,
38 "object": {"test": "test"},
39 "array": [
40 "string",
41 1,
42 3.0,
43 false,
44 {"test": "test"},
45 [1]
46 ]
47 }"#;
48
49 let v: serde_json::Value = serde_json::from_str(data)?;
50
51 assert_eq!(Some(v), serde_json::from_str(&Value::from_str(data)?.to_string()).ok());
52 # Ok(())
53 # }
54 ```
55 */
56 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
57 Display::fmt(&Value::Object(self.clone()), f)
58 }
59}
60
61impl FromIterator<(String, Value)> for Object {
62 /// Iterates over the key/value pairs of a JSON object.
63 fn from_iter<T: IntoIterator<Item = (String, Value)>>(iter: T) -> Self {
64 iter.into_iter()
65 .fold(Self::new(), |o, (k, v)| o.add(&k, &v))
66 }
67}
68
69impl Hash for Object {
70 fn hash<H: Hasher>(&self, state: &mut H) {
71 self.map.iter().for_each(|(k, v)| {
72 k.hash(state);
73 v.hash(state)
74 })
75 }
76}
77
78impl<'a> IntoIterator for &'a Object {
79 type Item = (String, Value);
80 type IntoIter = ObjectIter<'a>;
81
82 fn into_iter(self) -> ObjectIter<'a> {
83 self.iter()
84 }
85}
86
87impl Object {
88 /**
89 Adds a field to an object.
90 ```rust
91 # use immutable_json::api::Value::String;
92 # use immutable_json::object::Object;
93 # fn main() {
94 assert_eq!(Some("test".to_string()),
95 Object::new().add("test", &String("test".to_string())).get_string("test"));
96 # }
97 ```
98 */
99 pub fn add(&self, key: &str, value: &Value) -> Self {
100 Self {
101 map: hashmap::insert(&self.map, key.to_string(), value.clone()).0,
102 }
103 }
104
105 /**
106 Adds a field to an object as an array.
107 ```rust
108 # use immutable_json::array::Array;
109 # use immutable_json::object::Object;
110 # fn main() {
111 assert_eq!(Some(1),
112 Object::new()
113 .add_array("test", &Array::new().add_integer(1))
114 .get_array("test").and_then(|a| a.get_integer(0).ok()?));
115 # }
116 ```
117 */
118 pub fn add_array(&self, key: &str, value: &Array) -> Self {
119 self.add(key, &Value::Array(value.clone()))
120 }
121
122 pub fn add_array_p(&self, pointer: &str, value: &Array) -> Option<Self> {
123 self.add_p(pointer, &Value::Array(value.clone()))
124 }
125
126 /**
127 Adds a field to an object as a bool.
128 ```rust
129 # use immutable_json::object::Object;
130 # fn main() {
131 assert_eq!(Some(true), Object::new().add_bool("test", true).get_bool("test"));
132 # }
133 ```
134 */
135 pub fn add_bool(&self, key: &str, value: bool) -> Self {
136 self.add(key, &Value::Bool(value))
137 }
138
139 pub fn add_bool_p(&self, pointer: &str, value: bool) -> Option<Self> {
140 self.add_p(pointer, &Value::Bool(value))
141 }
142
143 /**
144 Adds a field to an object as a decimal.
145 ```rust
146 # use immutable_json::object::Object;
147 # fn main() {
148 assert_eq!(Some(3.0), Object::new().add_decimal("test", 3.0).get_decimal("test"));
149 # }
150 ```
151 */
152 pub fn add_decimal(&self, key: &str, value: f64) -> Self {
153 self.add(key, &Value::Number(Decimal(value)))
154 }
155
156 pub fn add_decimal_p(&self, pointer: &str, value: f64) -> Option<Self> {
157 self.add_p(pointer, &Value::Number(Number::Decimal(value)))
158 }
159
160 /**
161 Adds a field to an object as an integer.
162 ```rust
163 # use immutable_json::object::Object;
164 # fn main() {
165 assert_eq!(Some(3), Object::new().add_integer("test", 3).get_integer("test"));
166 # }
167 ```
168 */
169 pub fn add_integer(&self, key: &str, value: i128) -> Self {
170 self.add(key, &Value::Number(Integer(value)))
171 }
172
173 pub fn add_integer_p(&self, pointer: &str, value: i128) -> Option<Self> {
174 self.add_p(pointer, &Value::Number(Number::Integer(value)))
175 }
176
177 /**
178 Adds a field to an object as a number.
179 ```rust
180 # use immutable_json::object::Object;
181 # use immutable_json::api::Number::Integer;
182 # fn main() {
183 assert_eq!(Some(3),
184 Object::new()
185 .add_number("test", Integer(3))
186 .get_number("test").and_then(|n| n.as_integer()));
187 # }
188 ```
189 */
190 pub fn add_number(&self, key: &str, value: Number) -> Self {
191 self.add(key, &Value::Number(value))
192 }
193
194 pub fn add_number_p(&self, pointer: &str, value: Number) -> Option<Self> {
195 self.add_p(pointer, &Value::Number(value))
196 }
197
198 /**
199 Adds a field to an object as an object.
200 ```rust
201 # use immutable_json::object::Object;
202 # use immutable_json::api::Number::Integer;
203 # fn main() {
204 assert_eq!(Some(1),
205 Object::new()
206 .add_object("test", &Object::new().add_integer("test", 1))
207 .get_object("test").and_then(|o| o.get_integer("test")));
208 # }
209 ```
210 */
211 pub fn add_object(&self, key: &str, value: &Object) -> Self {
212 self.add(key, &Value::Object(value.clone()))
213 }
214
215 pub fn add_object_p(&self, pointer: &str, value: &Object) -> Option<Self> {
216 self.add_p(pointer, &Value::Object(value.clone()))
217 }
218
219 pub fn add_p(&self, pointer: &str, value: &Value) -> Option<Self> {
220 JsonPointer::add_pointer(pointer, &Value::Object(self.clone()), value)
221 .and_then(|v| v.as_object())
222 }
223
224 /**
225 Adds a field to an object as an integer.
226 ```rust
227 # use immutable_json::object::Object;
228 # fn main() {
229 assert_eq!(Some("test".to_string()),
230 Object::new().add_string("test", "test").get_string("test"));
231 # }
232 ```
233 */
234 pub fn add_string(&self, key: &str, value: &str) -> Self {
235 self.add(key, &Value::String(value.to_string()))
236 }
237
238 pub fn add_string_p(&self, pointer: &str, value: &str) -> Option<Self> {
239 self.add_p(pointer, &Value::String(value.to_string()))
240 }
241
242 /**
243 Returns a value from the object if it exists at the given key.
244 ```rust
245 # use immutable_json::object::Object;
246 # fn main() {
247 let object = Object::new().add_string("test1", "test");
248
249 assert_eq!(Some("test".to_string()), object.get_string("test1"));
250 assert_eq!(None, object.get_string("test2"));
251 # }
252 ```
253 */
254 pub fn get(&self, key: &str) -> Option<&Value> {
255 self.map.get(&key.to_string())
256 }
257
258 /**
259 Returns a value from the object if it exists at the given key and if it is an array.
260 Otherwise, `None` is returned.
261 ```rust
262 # use immutable_json::array::Array;
263 # use immutable_json::object::Object;
264 # fn main() {
265 let object = Object::new()
266 .add_array("test1", &Array::new().add_integer(3))
267 .add_integer("test2", 3);
268
269 assert_eq!(Some(3), object.get_array("test1").and_then(|a| a.get_integer(0).ok()?));
270 assert_eq!(None, object.get_array("test2"));
271 # }
272 ```
273 */
274 pub fn get_array(&self, key: &str) -> Option<Array> {
275 self.get(key).and_then(|v| v.as_array())
276 }
277
278 pub fn get_array_p(&self, pointer: &str) -> Option<Array> {
279 self.get_p(pointer).and_then(|v| v.as_array())
280 }
281
282 /**
283 Returns a value from the object if it exists at the given key and if it is a bool.
284 Otherwise, `None` is returned.
285 ```rust
286 # use immutable_json::object::Object;
287 # fn main() {
288 let object = Object::new()
289 .add_bool("test1", true)
290 .add_integer("test2", 3);
291
292 assert_eq!(Some(true), object.get_bool("test1"));
293 assert_eq!(None, object.get_string("test2"));
294 # }
295 ```
296 */
297 pub fn get_bool(&self, key: &str) -> Option<bool> {
298 self.get(key).and_then(|v| v.as_bool())
299 }
300
301 pub fn get_bool_p(&self, pointer: &str) -> Option<bool> {
302 self.get_p(pointer).and_then(|v| v.as_bool())
303 }
304
305 /**
306 Returns a value from the object if it exists at the given key and if it is a decimal.
307 Otherwise, `None` is returned.
308 ```rust
309 # use immutable_json::object::Object;
310 # fn main() {
311 let object = Object::new()
312 .add_decimal("test1", 3.0)
313 .add_integer("test2", 3);
314
315 assert_eq!(Some(3.0), object.get_decimal("test1"));
316 assert_eq!(None, object.get_string("test2"));
317 # }
318 ```
319 */
320 pub fn get_decimal(&self, key: &str) -> Option<f64> {
321 self.get(key).and_then(|v| v.as_decimal())
322 }
323
324 pub fn get_decimal_p(&self, pointer: &str) -> Option<f64> {
325 self.get_p(pointer).and_then(|v| v.as_decimal())
326 }
327
328 /**
329 Returns a value from the object if it exists at the given key and if it is an integer.
330 Otherwise, `None` is returned.
331 ```rust
332 # use immutable_json::object::Object;
333 # fn main() {
334 let object = Object::new()
335 .add_decimal("test1", 3.0)
336 .add_integer("test2", 3);
337
338 assert_eq!(Some(3.0), object.get_decimal("test1"));
339 assert_eq!(None, object.get_string("test2"));
340 # }
341 ```
342 */
343 pub fn get_integer(&self, key: &str) -> Option<i128> {
344 self.get(key).and_then(|v| v.as_integer())
345 }
346
347 pub fn get_integer_p(&self, pointer: &str) -> Option<i128> {
348 self.get_p(pointer).and_then(|v| v.as_integer())
349 }
350
351 /**
352 Returns a value from the object if it exists at the given key and if it is a number.
353 Otherwise, `None` is returned.
354 ```rust
355 # use immutable_json::api::Number;
356 # use immutable_json::object::Object;
357 # fn main() {
358 let object = Object::new()
359 .add_number("test1", Number::Decimal(3.0))
360 .add_integer("test2", 3);
361
362 assert_eq!(Some(3.0), object.get_number("test1").and_then(|n| n.as_decimal()));
363 assert_eq!(None, object.get_string("test2"));
364 # }
365 ```
366 */
367 pub fn get_number(&self, key: &str) -> Option<Number> {
368 self.get(key).and_then(|v| v.as_number())
369 }
370
371 pub fn get_number_p(&self, pointer: &str) -> Option<Number> {
372 self.get_p(pointer).and_then(|v| v.as_number())
373 }
374
375 /**
376 Returns a value from the object if it exists at the given key and if it is an object.
377 Otherwise, `None` is returned.
378 ```rust
379 # use immutable_json::object::Object;
380 # fn main() {
381 let object = Object::new()
382 .add_object("test1", &Object::new().add_integer("test", 3))
383 .add_integer("test2", 3);
384
385 assert_eq!(Some(3), object.get_object("test1").and_then(|a| a.get_integer("test")));
386 assert_eq!(None, object.get_array("test2"));
387 # }
388 ```
389 */
390 pub fn get_object(&self, key: &str) -> Option<Object> {
391 self.get(key).and_then(|v| v.as_object())
392 }
393
394 pub fn get_object_p(&self, pointer: &str) -> Option<Object> {
395 self.get_p(pointer).and_then(|v| v.as_object())
396 }
397
398 pub fn get_p(&self, pointer: &str) -> Option<Value> {
399 JsonPointer::get_pointer(pointer, &Value::Object(self.clone()))
400 }
401
402 /**
403 Returns a value from the object if it exists at the given key and if it is a string.
404 Otherwise, `None` is returned.
405 ```rust
406 # use immutable_json::object::Object;
407 # fn main() {
408 let object = Object::new()
409 .add_string("test1", "test")
410 .add_integer("test2", 3);
411
412 assert_eq!(Some("test".to_string()), object.get_string("test1"));
413 assert_eq!(None, object.get_string("test2"));
414 # }
415 ```
416 */
417 pub fn get_string(&self, key: &str) -> Option<String> {
418 self.get(key).and_then(|v| v.as_string())
419 }
420
421 pub fn get_string_p(&self, pointer: &str) -> Option<String> {
422 self.get_p(pointer).and_then(|v| v.as_string())
423 }
424
425 /**
426 Returns `true` if the object has a field with the given key.
427 ```rust
428 # use immutable_json::object::Object;
429 # fn main() {
430 let object = Object::new().add_string("test1", "test");
431
432 assert_eq!(true, object.has_key("test1"));
433 assert_eq!(false, object.has_key("test2"));
434 # }
435 ```
436 */
437 pub fn has_key(&self, key: &str) -> bool {
438 self.map.contains_key(&key.to_string())
439 }
440
441 /**
442 Returns an iterator over the key/value tuples of the object.
443 ```rust
444 # use immutable_json::object::Object;
445 # fn main() {
446 let object = Object::new().add_string("test1", "test1").add_integer("test2", 1);
447
448 assert_eq!(object, Object::from_iter(object.iter()));
449 # }
450 ```
451 */
452 pub fn iter(&'_ self) -> ObjectIter<'_> {
453 ObjectIter {
454 iter: self.map.iter(),
455 }
456 }
457
458 /**
459 Merges the other object into this one, overwriting existing entries.
460 ```rust
461 # use immutable_json::object::Object;
462 # fn main() {
463 let object = Object::new().add_string("test1", "test1").add_integer("test2", 1);
464 let other = Object::new().add_string("test1", "changed").add_integer("test3", 2);
465 let merged = Object::new().add_string("test1", "changed").add_integer("test2", 1).add_integer("test3", 2);
466
467 assert_eq!(merged, object.merge(&other));
468 # }
469 ```
470 */
471 pub fn merge(&self, other: &Object) -> Self {
472 Self {
473 map: hashmap::merge(&other.map, &self.map),
474 }
475 }
476
477 /// Create an empty JSON object.
478 pub fn new() -> Self {
479 Self {
480 map: HashMap::new(),
481 }
482 }
483
484 /**
485 Removes the field with the given key from the object.
486 ```rust
487 # use immutable_json::object::Object;
488 # fn main() {
489 let object = Object::new().add_string("test", "test");
490
491 assert_eq!(true, object.has_key("test"));
492 assert_eq!(false, object.remove("test").has_key("test"));
493 # }
494 ```
495 */
496 pub fn remove(&self, key: &str) -> Self {
497 Self {
498 map: hashmap::remove(&self.map, &key.to_string()).0,
499 }
500 }
501
502 pub fn remove_p(&self, pointer: &str) -> Option<Self> {
503 JsonPointer::remove_pointer(pointer, &Value::Object(self.clone()))
504 .and_then(|v| v.as_object())
505 }
506
507 /**
508 Sets a field to an object.
509 ```rust
510 # use immutable_json::api::Value::String;
511 # use immutable_json::object::Object;
512 # fn main() {
513 assert_eq!(Some("test".to_string()),
514 Object::new().set("test", &String("test".to_string())).get_string("test"));
515 # }
516 ```
517 */
518 pub fn set(&self, key: &str, value: &Value) -> Self {
519 Self {
520 map: self.map.update(key.to_string(), value.clone()),
521 }
522 }
523
524 /**
525 Sets a field to an object as an array.
526 ```rust
527 # use immutable_json::array::Array;
528 # use immutable_json::object::Object;
529 # fn main() {
530 assert_eq!(Some(1),
531 Object::new()
532 .set_array("test", &Array::new().add_integer(1))
533 .get_array("test").and_then(|a| a.get_integer(0).ok()?));
534 # }
535 ```
536 */
537 pub fn set_array(&self, key: &str, value: &Array) -> Self {
538 self.set(key, &Value::Array(value.clone()))
539 }
540
541 pub fn set_array_p(&self, pointer: &str, value: &Array) -> Option<Self> {
542 self.set_p(pointer, &Value::Array(value.clone()))
543 }
544
545 /**
546 Sets a field to an object as a bool.
547 ```rust
548 # use immutable_json::object::Object;
549 # fn main() {
550 assert_eq!(Some(true), Object::new().set_bool("test", true).get_bool("test"));
551 # }
552 ```
553 */
554 pub fn set_bool(&self, key: &str, value: bool) -> Self {
555 self.set(key, &Value::Bool(value))
556 }
557
558 pub fn set_bool_p(&self, pointer: &str, value: bool) -> Option<Self> {
559 self.set_p(pointer, &Value::Bool(value))
560 }
561
562 /**
563 Sets a field to an object as a decimal.
564 ```rust
565 # use immutable_json::object::Object;
566 # fn main() {
567 assert_eq!(Some(3.0), Object::new().set_decimal("test", 3.0).get_decimal("test"));
568 # }
569 ```
570 */
571 pub fn set_decimal(&self, key: &str, value: f64) -> Self {
572 self.set(key, &Value::Number(Decimal(value)))
573 }
574
575 pub fn set_decimal_p(&self, pointer: &str, value: f64) -> Option<Self> {
576 self.set_p(pointer, &Value::Number(Number::Decimal(value)))
577 }
578
579 /**
580 Sets a field to an object as an integer.
581 ```rust
582 # use immutable_json::object::Object;
583 # fn main() {
584 assert_eq!(Some(3), Object::new().set_integer("test", 3).get_integer("test"));
585 # }
586 ```
587 */
588 pub fn set_integer(&self, key: &str, value: i128) -> Self {
589 self.set(key, &Value::Number(Integer(value)))
590 }
591
592 pub fn set_integer_p(&self, pointer: &str, value: i128) -> Option<Self> {
593 self.set_p(pointer, &Value::Number(Number::Integer(value)))
594 }
595
596 /**
597 Sets a field to an object as a number.
598 ```rust
599 # use immutable_json::object::Object;
600 # use immutable_json::api::Number::Integer;
601 # fn main() {
602 assert_eq!(Some(3),
603 Object::new()
604 .set_number("test", Integer(3))
605 .get_number("test").and_then(|n| n.as_integer()));
606 # }
607 ```
608 */
609 pub fn set_number(&self, key: &str, value: Number) -> Self {
610 self.add(key, &Value::Number(value))
611 }
612
613 pub fn set_number_p(&self, pointer: &str, value: Number) -> Option<Self> {
614 self.add_p(pointer, &Value::Number(value))
615 }
616
617 /**
618 Sets a field to an object as an object.
619 ```rust
620 # use immutable_json::object::Object;
621 # use immutable_json::api::Number::Integer;
622 # fn main() {
623 assert_eq!(Some(1),
624 Object::new()
625 .set_object("test", &Object::new().add_integer("test", 1))
626 .get_object("test").and_then(|o| o.get_integer("test")));
627 # }
628 ```
629 */
630 pub fn set_object(&self, key: &str, value: &Object) -> Self {
631 self.set(key, &Value::Object(value.clone()))
632 }
633
634 pub fn set_object_p(&self, pointer: &str, value: &Object) -> Option<Self> {
635 self.set_p(pointer, &Value::Object(value.clone()))
636 }
637
638 pub fn set_p(&self, pointer: &str, value: &Value) -> Option<Self> {
639 JsonPointer::set_pointer(pointer, &Value::Object(self.clone()), value)
640 .and_then(|v| v.as_object())
641 }
642
643 /**
644 Sets a field to an object as an integer.
645 ```rust
646 # use immutable_json::object::Object;
647 # fn main() {
648 assert_eq!(Some("test".to_string()),
649 Object::new().set_string("test", "test").get_string("test"));
650 # }
651 ```
652 */
653 pub fn set_string(&self, key: &str, value: &str) -> Self {
654 self.set(key, &Value::String(value.to_string()))
655 }
656
657 pub fn set_string_p(&self, pointer: &str, value: &str) -> Option<Self> {
658 self.set_p(pointer, &Value::String(value.to_string()))
659 }
660}
661
662#[derive(Clone)]
663pub struct ObjectIter<'a> {
664 iter: Iter<'a, String, Value, DefaultSharedPtr>,
665}
666
667impl<'a> Iterator for ObjectIter<'a> {
668 type Item = (String, Value);
669
670 fn next(&mut self) -> Option<Self::Item> {
671 self.iter.next().map(|i| (i.0.clone(), i.1.clone()))
672 }
673}