1extern crate alloc;
26
27use alloc::ffi::CString;
28use alloc::string::String;
29use alloc::vec::Vec;
30use core::ffi::{CStr, c_char, c_int};
31use core::ptr;
32use core::fmt::Display;
33
34use crate::cjson_ffi::*;
35
36pub type CJsonResult<T> = Result<T, CJsonError>;
38
39#[derive(Debug, Clone, PartialEq, Eq)]
41pub enum CJsonError {
42 ParseError,
44 NullPointer,
46 InvalidUtf8,
48 NotFound,
50 TypeError,
52 AllocationError,
54 InvalidOperation,
56}
57
58impl Display for CJsonError {
59 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
60 match self {
61 CJsonError::ParseError => write!(f, "Failed to parse JSON"),
62 CJsonError::NullPointer => write!(f, "Null pointer encountered"),
63 CJsonError::InvalidUtf8 => write!(f, "Invalid UTF-8 in string"),
64 CJsonError::NotFound => write!(f, "Item not found"),
65 CJsonError::TypeError => write!(f, "Wrong type"),
66 CJsonError::AllocationError => write!(f, "Memory allocation failed"),
67 CJsonError::InvalidOperation => write!(f, "Invalid operation"),
68 }
69 }
70}
71
72#[cfg(feature = "disable_panic")]
73impl From<osal_rs_serde::Error> for CJsonError {
74 fn from(err: osal_rs_serde::Error) -> Self {
75 use osal_rs_serde::Error::*;
76
77 match err {
78 BufferTooSmall => CJsonError::AllocationError,
79 UnexpectedEof => CJsonError::ParseError,
80 InvalidData => CJsonError::ParseError,
81 TypeMismatch => CJsonError::TypeError,
82 OutOfRange => CJsonError::NotFound,
83 Custom(_) => CJsonError::InvalidOperation,
84 Unsupported => CJsonError::InvalidOperation,
85 }
86 }
87}
88
89#[derive(Debug, Clone)]
91pub struct CJson {
92 ptr: *mut cJSON,
93}
94
95impl CJson {
96 pub(crate) unsafe fn from_ptr(ptr: *mut cJSON) -> CJsonResult<Self> {
101 if ptr.is_null() {
102 Err(CJsonError::NullPointer)
103 } else {
104 Ok(CJson { ptr })
105 }
106 }
107
108 pub fn as_ptr(&self) -> *const cJSON {
110 self.ptr
111 }
112
113 pub fn as_mut_ptr(&mut self) -> *mut cJSON {
115 self.ptr
116 }
117
118 pub fn into_raw(self) -> *mut cJSON {
120 let ptr = self.ptr;
121 core::mem::forget(self);
122 ptr
123 }
124
125 pub fn drop(&self) {
127 if !self.ptr.is_null() {
128 unsafe { cJSON_Delete(self.ptr) };
129 }
130 }
131
132 pub fn parse(json: &str) -> CJsonResult<Self> {
138 let c_str = CString::new(json).map_err(|_| CJsonError::InvalidUtf8)?;
139 let ptr = unsafe { cJSON_Parse(c_str.as_ptr()) };
140 unsafe { Self::from_ptr(ptr) }
141 }
142
143 pub fn parse_with_length(json: &str, length: usize) -> CJsonResult<Self> {
145 let c_str = CString::new(json).map_err(|_| CJsonError::InvalidUtf8)?;
146 let ptr = unsafe { cJSON_ParseWithLength(c_str.as_ptr(), length) };
147 unsafe { Self::from_ptr(ptr) }
148 }
149
150 pub fn parse_with_opts(json: &str, require_null_terminated: bool) -> CJsonResult<Self> {
152 let c_str = CString::new(json).map_err(|_| CJsonError::InvalidUtf8)?;
153 let ptr = unsafe {
154 cJSON_ParseWithOpts(
155 c_str.as_ptr(),
156 ptr::null_mut(),
157 if require_null_terminated { 1 } else { 0 },
158 )
159 };
160 unsafe { Self::from_ptr(ptr) }
161 }
162
163 pub fn print(&self) -> CJsonResult<String> {
169 let c_str = unsafe { cJSON_Print(self.ptr) };
170 if c_str.is_null() {
171 return Err(CJsonError::AllocationError);
172 }
173 let rust_str = unsafe { CStr::from_ptr(c_str).to_string_lossy().into_owned() };
174 unsafe { cJSON_free(c_str as *mut core::ffi::c_void) };
175 Ok(rust_str)
176 }
177
178 pub fn print_unformatted(&self) -> CJsonResult<String> {
180 let c_str = unsafe { cJSON_PrintUnformatted(self.ptr) };
181 if c_str.is_null() {
182 return Err(CJsonError::AllocationError);
183 }
184 let rust_str = unsafe { CStr::from_ptr(c_str).to_string_lossy().into_owned() };
185 unsafe { cJSON_free(c_str as *mut core::ffi::c_void) };
186 Ok(rust_str)
187 }
188
189 pub fn is_invalid(&self) -> bool {
195 unsafe { cJSON_IsInvalid(self.ptr) != 0 }
196 }
197
198 pub fn is_false(&self) -> bool {
200 unsafe { cJSON_IsFalse(self.ptr) != 0 }
201 }
202
203 pub fn is_true(&self) -> bool {
205 unsafe { cJSON_IsTrue(self.ptr) != 0 }
206 }
207
208 pub fn is_bool(&self) -> bool {
210 unsafe { cJSON_IsBool(self.ptr) != 0 }
211 }
212
213 pub fn is_null(&self) -> bool {
215 unsafe { cJSON_IsNull(self.ptr) != 0 }
216 }
217
218 pub fn is_number(&self) -> bool {
220 unsafe { cJSON_IsNumber(self.ptr) != 0 }
221 }
222
223 pub fn is_string(&self) -> bool {
225 unsafe { cJSON_IsString(self.ptr) != 0 }
226 }
227
228 pub fn is_array(&self) -> bool {
230 unsafe { cJSON_IsArray(self.ptr) != 0 }
231 }
232
233 pub fn is_object(&self) -> bool {
235 unsafe { cJSON_IsObject(self.ptr) != 0 }
236 }
237
238 pub fn is_raw(&self) -> bool {
240 unsafe { cJSON_IsRaw(self.ptr) != 0 }
241 }
242
243 pub fn get_string_value(&self) -> CJsonResult<String> {
249 if !self.is_string() {
250 return Err(CJsonError::TypeError);
251 }
252 let c_str = unsafe { cJSON_GetStringValue(self.ptr) };
253 if c_str.is_null() {
254 return Err(CJsonError::NullPointer);
255 }
256 Ok(unsafe { CStr::from_ptr(c_str).to_string_lossy().into_owned() })
257 }
258
259 pub fn get_number_value(&self) -> CJsonResult<f64> {
261 if !self.is_number() {
262 return Err(CJsonError::TypeError);
263 }
264 Ok(unsafe { cJSON_GetNumberValue(self.ptr) })
265 }
266
267 pub fn get_int_value(&self) -> CJsonResult<i32> {
269 if !self.is_number() {
270 return Err(CJsonError::TypeError);
271 }
272 Ok(unsafe { (*self.ptr).valueint })
273 }
274
275 pub fn get_bool_value(&self) -> CJsonResult<bool> {
277 if !self.is_bool() {
278 return Err(CJsonError::TypeError);
279 }
280 Ok(self.is_true())
281 }
282
283 pub fn get_array_size(&self) -> CJsonResult<usize> {
289 if !self.is_array() {
290 return Err(CJsonError::TypeError);
291 }
292 Ok(unsafe { cJSON_GetArraySize(self.ptr) as usize })
293 }
294
295 pub fn get_array_item(&self, index: usize) -> CJsonResult<CJsonRef> {
297 if !self.is_array() {
298 return Err(CJsonError::TypeError);
299 }
300 let ptr = unsafe { cJSON_GetArrayItem(self.ptr, index as c_int) };
301 unsafe { CJsonRef::from_ptr(ptr) }.map_err(|_| CJsonError::NotFound)
302 }
303
304 pub fn get_object_item(&self, key: &str) -> CJsonResult<CJsonRef> {
310 if !self.is_object() {
311 return Err(CJsonError::TypeError);
312 }
313 let c_key = CString::new(key).map_err(|_| CJsonError::InvalidUtf8)?;
314 let ptr = unsafe { cJSON_GetObjectItem(self.ptr, c_key.as_ptr()) };
315 unsafe { CJsonRef::from_ptr(ptr) }.map_err(|_| CJsonError::NotFound)
316 }
317
318 pub fn get_object_item_case_sensitive(&self, key: &str) -> CJsonResult<CJsonRef> {
320 if !self.is_object() {
321 return Err(CJsonError::TypeError);
322 }
323 let c_key = CString::new(key).map_err(|_| CJsonError::InvalidUtf8)?;
324 let ptr = unsafe { cJSON_GetObjectItemCaseSensitive(self.ptr, c_key.as_ptr()) };
325 unsafe { CJsonRef::from_ptr(ptr) }.map_err(|_| CJsonError::NotFound)
326 }
327
328 pub fn has_object_item(&self, key: &str) -> bool {
330 if !self.is_object() {
331 return false;
332 }
333 let Ok(c_key) = CString::new(key) else {
334 return false;
335 };
336 unsafe { cJSON_HasObjectItem(self.ptr, c_key.as_ptr()) != 0 }
337 }
338
339 pub fn create_null() -> CJsonResult<Self> {
345 let ptr = unsafe { cJSON_CreateNull() };
346 unsafe { Self::from_ptr(ptr) }
347 }
348
349 pub fn create_true() -> CJsonResult<Self> {
351 let ptr = unsafe { cJSON_CreateTrue() };
352 unsafe { Self::from_ptr(ptr) }
353 }
354
355 pub fn create_false() -> CJsonResult<Self> {
357 let ptr = unsafe { cJSON_CreateFalse() };
358 unsafe { Self::from_ptr(ptr) }
359 }
360
361 pub fn create_bool(value: bool) -> CJsonResult<Self> {
363 let ptr = unsafe { cJSON_CreateBool(if value { 1 } else { 0 }) };
364 unsafe { Self::from_ptr(ptr) }
365 }
366
367 pub fn create_number(value: f64) -> CJsonResult<Self> {
369 let ptr = unsafe { cJSON_CreateNumber(value) };
370 unsafe { Self::from_ptr(ptr) }
371 }
372
373 pub fn create_string(value: &str) -> CJsonResult<Self> {
375 let c_str = CString::new(value).map_err(|_| CJsonError::InvalidUtf8)?;
376 let ptr = unsafe { cJSON_CreateString(c_str.as_ptr()) };
377 unsafe { Self::from_ptr(ptr) }
378 }
379
380 pub fn create_array() -> CJsonResult<Self> {
382 let ptr = unsafe { cJSON_CreateArray() };
383 unsafe { Self::from_ptr(ptr) }
384 }
385
386 pub fn create_object() -> CJsonResult<Self> {
388 let ptr = unsafe { cJSON_CreateObject() };
389 unsafe { Self::from_ptr(ptr) }
390 }
391
392 pub fn create_int_array(values: &[i32]) -> CJsonResult<Self> {
394 let ptr = unsafe { cJSON_CreateIntArray(values.as_ptr(), values.len() as c_int) };
395 unsafe { Self::from_ptr(ptr) }
396 }
397
398 pub fn create_double_array(values: &[f64]) -> CJsonResult<Self> {
400 let ptr = unsafe { cJSON_CreateDoubleArray(values.as_ptr(), values.len() as c_int) };
401 unsafe { Self::from_ptr(ptr) }
402 }
403
404 pub fn create_string_array(values: &[&str]) -> CJsonResult<Self> {
406 let c_strings: Vec<CString> = values
407 .iter()
408 .map(|s| CString::new(*s))
409 .collect::<Result<_, _>>()
410 .map_err(|_| CJsonError::InvalidUtf8)?;
411
412 let c_ptrs: Vec<*const c_char> = c_strings.iter().map(|s| s.as_ptr()).collect();
413
414 let ptr = unsafe { cJSON_CreateStringArray(c_ptrs.as_ptr(), c_ptrs.len() as c_int) };
415 unsafe { Self::from_ptr(ptr) }
416 }
417
418 pub fn add_item_to_array(&mut self, item: CJson) -> CJsonResult<()> {
424 if !self.is_array() {
425 return Err(CJsonError::TypeError);
426 }
427 let result = unsafe { cJSON_AddItemToArray(self.ptr, item.into_raw()) };
428 if result != 0 {
429 Ok(())
430 } else {
431 Err(CJsonError::InvalidOperation)
432 }
433 }
434
435 pub fn delete_item_from_array(&mut self, index: usize) -> CJsonResult<()> {
437 if !self.is_array() {
438 return Err(CJsonError::TypeError);
439 }
440 unsafe { cJSON_DeleteItemFromArray(self.ptr, index as c_int) };
441 Ok(())
442 }
443
444 pub fn detach_item_from_array(&mut self, index: usize) -> CJsonResult<CJson> {
446 if !self.is_array() {
447 return Err(CJsonError::TypeError);
448 }
449 let ptr = unsafe { cJSON_DetachItemFromArray(self.ptr, index as c_int) };
450 unsafe { Self::from_ptr(ptr) }
451 }
452
453 pub fn add_item_to_object(&mut self, key: &str, item: CJson) -> CJsonResult<()> {
459 if !self.is_object() {
460 return Err(CJsonError::TypeError);
461 }
462 let c_key = CString::new(key).map_err(|_| CJsonError::InvalidUtf8)?;
463 let result = unsafe { cJSON_AddItemToObject(self.ptr, c_key.as_ptr(), item.into_raw()) };
464 if result != 0 {
465 Ok(())
466 } else {
467 Err(CJsonError::InvalidOperation)
468 }
469 }
470
471 pub fn add_null_to_object(&mut self, key: &str) -> CJsonResult<()> {
473 if !self.is_object() {
474 return Err(CJsonError::TypeError);
475 }
476 let c_key = CString::new(key).map_err(|_| CJsonError::InvalidUtf8)?;
477 let ptr = unsafe { cJSON_AddNullToObject(self.ptr, c_key.as_ptr()) };
478 if ptr.is_null() {
479 Err(CJsonError::AllocationError)
480 } else {
481 Ok(())
482 }
483 }
484
485 pub fn add_true_to_object(&mut self, key: &str) -> CJsonResult<()> {
487 if !self.is_object() {
488 return Err(CJsonError::TypeError);
489 }
490 let c_key = CString::new(key).map_err(|_| CJsonError::InvalidUtf8)?;
491 let ptr = unsafe { cJSON_AddTrueToObject(self.ptr, c_key.as_ptr()) };
492 if ptr.is_null() {
493 Err(CJsonError::AllocationError)
494 } else {
495 Ok(())
496 }
497 }
498
499 pub fn add_false_to_object(&mut self, key: &str) -> CJsonResult<()> {
501 if !self.is_object() {
502 return Err(CJsonError::TypeError);
503 }
504 let c_key = CString::new(key).map_err(|_| CJsonError::InvalidUtf8)?;
505 let ptr = unsafe { cJSON_AddFalseToObject(self.ptr, c_key.as_ptr()) };
506 if ptr.is_null() {
507 Err(CJsonError::AllocationError)
508 } else {
509 Ok(())
510 }
511 }
512
513 pub fn add_bool_to_object(&mut self, key: &str, value: bool) -> CJsonResult<()> {
515 if !self.is_object() {
516 return Err(CJsonError::TypeError);
517 }
518 let c_key = CString::new(key).map_err(|_| CJsonError::InvalidUtf8)?;
519 let ptr = unsafe {
520 cJSON_AddBoolToObject(self.ptr, c_key.as_ptr(), if value { 1 } else { 0 })
521 };
522 if ptr.is_null() {
523 Err(CJsonError::AllocationError)
524 } else {
525 Ok(())
526 }
527 }
528
529 pub fn add_number_to_object(&mut self, key: &str, value: f64) -> CJsonResult<()> {
531 if !self.is_object() {
532 return Err(CJsonError::TypeError);
533 }
534 let c_key = CString::new(key).map_err(|_| CJsonError::InvalidUtf8)?;
535 let ptr = unsafe { cJSON_AddNumberToObject(self.ptr, c_key.as_ptr(), value) };
536 if ptr.is_null() {
537 Err(CJsonError::AllocationError)
538 } else {
539 Ok(())
540 }
541 }
542
543 pub fn add_string_to_object(&mut self, key: &str, value: &str) -> CJsonResult<()> {
545 if !self.is_object() {
546 return Err(CJsonError::TypeError);
547 }
548 let c_key = CString::new(key).map_err(|_| CJsonError::InvalidUtf8)?;
549 let c_value = CString::new(value).map_err(|_| CJsonError::InvalidUtf8)?;
550 let ptr = unsafe { cJSON_AddStringToObject(self.ptr, c_key.as_ptr(), c_value.as_ptr()) };
551 if ptr.is_null() {
552 Err(CJsonError::AllocationError)
553 } else {
554 Ok(())
555 }
556 }
557
558 pub fn delete_item_from_object(&mut self, key: &str) -> CJsonResult<()> {
560 if !self.is_object() {
561 return Err(CJsonError::TypeError);
562 }
563 let c_key = CString::new(key).map_err(|_| CJsonError::InvalidUtf8)?;
564 unsafe { cJSON_DeleteItemFromObject(self.ptr, c_key.as_ptr()) };
565 Ok(())
566 }
567
568 pub fn detach_item_from_object(&mut self, key: &str) -> CJsonResult<CJson> {
570 if !self.is_object() {
571 return Err(CJsonError::TypeError);
572 }
573 let c_key = CString::new(key).map_err(|_| CJsonError::InvalidUtf8)?;
574 let ptr = unsafe { cJSON_DetachItemFromObject(self.ptr, c_key.as_ptr()) };
575 unsafe { Self::from_ptr(ptr) }
576 }
577
578 pub fn duplicate(&self, recurse: bool) -> CJsonResult<Self> {
584 let ptr = unsafe { cJSON_Duplicate(self.ptr, if recurse { 1 } else { 0 }) };
585 unsafe { Self::from_ptr(ptr) }
586 }
587
588 pub fn compare(&self, other: &CJson, case_sensitive: bool) -> bool {
590 unsafe {
591 cJSON_Compare(self.ptr, other.ptr, if case_sensitive { 1 } else { 0 }) != 0
592 }
593 }
594}
595
596pub struct CJsonRef {
607 ptr: *mut cJSON,
608}
609
610impl CJsonRef {
611 pub(crate) unsafe fn from_ptr(ptr: *mut cJSON) -> CJsonResult<Self> {
616 if ptr.is_null() {
617 Err(CJsonError::NullPointer)
618 } else {
619 Ok(CJsonRef { ptr })
620 }
621 }
622
623 pub fn as_ptr(&self) -> *const cJSON {
625 self.ptr
626 }
627
628 pub fn is_string(&self) -> bool {
630 unsafe { cJSON_IsString(self.ptr) != 0 }
631 }
632
633 pub fn is_number(&self) -> bool {
635 unsafe { cJSON_IsNumber(self.ptr) != 0 }
636 }
637
638 pub fn is_bool(&self) -> bool {
640 unsafe { cJSON_IsBool(self.ptr) != 0 }
641 }
642
643 pub fn is_null(&self) -> bool {
645 unsafe { cJSON_IsNull(self.ptr) != 0 }
646 }
647
648 pub fn is_array(&self) -> bool {
650 unsafe { cJSON_IsArray(self.ptr) != 0 }
651 }
652
653 pub fn is_object(&self) -> bool {
655 unsafe { cJSON_IsObject(self.ptr) != 0 }
656 }
657
658 pub fn get_string_value(&self) -> CJsonResult<String> {
660 if !self.is_string() {
661 return Err(CJsonError::TypeError);
662 }
663 let c_str = unsafe { cJSON_GetStringValue(self.ptr) };
664 if c_str.is_null() {
665 return Err(CJsonError::NullPointer);
666 }
667 Ok(unsafe { CStr::from_ptr(c_str).to_string_lossy().into_owned() })
668 }
669
670 pub fn get_number_value(&self) -> CJsonResult<f64> {
672 if !self.is_number() {
673 return Err(CJsonError::TypeError);
674 }
675 Ok(unsafe { cJSON_GetNumberValue(self.ptr) })
676 }
677
678 pub fn get_int_value(&self) -> CJsonResult<i32> {
680 if !self.is_number() {
681 return Err(CJsonError::TypeError);
682 }
683 Ok(unsafe { (*self.ptr).valueint })
684 }
685
686 pub fn get_bool_value(&self) -> CJsonResult<bool> {
688 if !self.is_bool() {
689 return Err(CJsonError::TypeError);
690 }
691 Ok(unsafe { cJSON_IsTrue(self.ptr) != 0 })
692 }
693
694 pub fn get_array_size(&self) -> CJsonResult<usize> {
696 if !self.is_array() {
697 return Err(CJsonError::TypeError);
698 }
699 Ok(unsafe { cJSON_GetArraySize(self.ptr) as usize })
700 }
701
702 pub fn get_array_item(&self, index: usize) -> CJsonResult<CJsonRef> {
704 if !self.is_array() {
705 return Err(CJsonError::TypeError);
706 }
707 let ptr = unsafe { cJSON_GetArrayItem(self.ptr, index as c_int) };
708 unsafe { CJsonRef::from_ptr(ptr) }.map_err(|_| CJsonError::NotFound)
709 }
710
711 pub fn get_object_item(&self, key: &str) -> CJsonResult<CJsonRef> {
713 if !self.is_object() {
714 return Err(CJsonError::TypeError);
715 }
716 let c_key = CString::new(key).map_err(|_| CJsonError::InvalidUtf8)?;
717 let ptr = unsafe { cJSON_GetObjectItem(self.ptr, c_key.as_ptr()) };
718 unsafe { CJsonRef::from_ptr(ptr) }.map_err(|_| CJsonError::NotFound)
719 }
720}
721
722#[allow(dead_code)]
724pub fn version() -> String {
725 let c_str = unsafe { cJSON_Version() };
726 unsafe { CStr::from_ptr(c_str).to_string_lossy().into_owned() }
727}
728
729#[allow(dead_code)]
731pub fn get_error_ptr() -> Option<String> {
732 let c_str = unsafe { cJSON_GetErrorPtr() };
733 if c_str.is_null() {
734 None
735 } else {
736 Some(unsafe { CStr::from_ptr(c_str).to_string_lossy().into_owned() })
737 }
738}
739
740#[allow(dead_code)]
742pub fn minify(json: &mut String) {
743 let c_str = CString::new(json.as_str()).expect("CString conversion failed");
744 unsafe {
745 let ptr = c_str.as_ptr() as *mut c_char;
746 cJSON_Minify(ptr);
747 *json = CStr::from_ptr(ptr).to_string_lossy().into_owned();
748 }
749}
750
751#[cfg(test)]
752mod tests {
753 use super::*;
754
755 #[test]
756 fn test_parse_simple_object() {
757 let json = r#"{"name":"John","age":30}"#;
758 let parsed = CJson::parse(json).unwrap();
759 assert!(parsed.is_object());
760 }
761
762 #[test]
763 fn test_parse_array() {
764 let json = r#"[1,2,3,4,5]"#;
765 let parsed = CJson::parse(json).unwrap();
766 assert!(parsed.is_array());
767 assert_eq!(parsed.get_array_size().unwrap(), 5);
768 }
769
770 #[test]
771 fn test_create_and_get_string() {
772 let json = CJson::create_string("Hello, World!").unwrap();
773 assert!(json.is_string());
774 assert_eq!(json.get_string_value().unwrap(), "Hello, World!");
775 }
776
777 #[test]
778 fn test_create_and_get_number() {
779 let json = CJson::create_number(42.5).unwrap();
780 assert!(json.is_number());
781 assert_eq!(json.get_number_value().unwrap(), 42.5);
782 }
783
784 #[test]
785 fn test_create_and_get_bool() {
786 let json_true = CJson::create_true().unwrap();
787 assert!(json_true.is_true());
788 assert!(json_true.is_bool());
789 assert_eq!(json_true.get_bool_value().unwrap(), true);
790
791 let json_false = CJson::create_false().unwrap();
792 assert!(json_false.is_false());
793 assert!(json_false.is_bool());
794 assert_eq!(json_false.get_bool_value().unwrap(), false);
795 }
796
797 #[test]
798 fn test_create_null() {
799 let json = CJson::create_null().unwrap();
800 assert!(json.is_null());
801 }
802
803 #[test]
804 fn test_create_object_and_add_items() {
805 let mut obj = CJson::create_object().unwrap();
806 obj.add_string_to_object("name", "Alice").unwrap();
807 obj.add_number_to_object("age", 25.0).unwrap();
808 obj.add_bool_to_object("active", true).unwrap();
809
810 assert!(obj.is_object());
811 assert!(obj.has_object_item("name"));
812 assert!(obj.has_object_item("age"));
813 assert!(obj.has_object_item("active"));
814
815 let name = obj.get_object_item("name").unwrap();
816 assert_eq!(name.get_string_value().unwrap(), "Alice");
817
818 let age = obj.get_object_item("age").unwrap();
819 assert_eq!(age.get_number_value().unwrap(), 25.0);
820 }
821
822 #[test]
823 fn test_create_array_and_add_items() {
824 let mut arr = CJson::create_array().unwrap();
825 arr.add_item_to_array(CJson::create_number(1.0).unwrap()).unwrap();
826 arr.add_item_to_array(CJson::create_number(2.0).unwrap()).unwrap();
827 arr.add_item_to_array(CJson::create_number(3.0).unwrap()).unwrap();
828
829 assert!(arr.is_array());
830 assert_eq!(arr.get_array_size().unwrap(), 3);
831
832 let item = arr.get_array_item(1).unwrap();
833 assert_eq!(item.get_number_value().unwrap(), 2.0);
834 }
835
836 #[test]
837 fn test_print_formatted() {
838 let mut obj = CJson::create_object().unwrap();
839 obj.add_string_to_object("key", "value").unwrap();
840
841 let json_str = obj.print().unwrap();
842 assert!(json_str.contains("key"));
843 assert!(json_str.contains("value"));
844 }
845
846 #[test]
847 fn test_print_unformatted() {
848 let mut obj = CJson::create_object().unwrap();
849 obj.add_string_to_object("key", "value").unwrap();
850
851 let json_str = obj.print_unformatted().unwrap();
852 assert!(json_str.contains("key"));
853 assert!(json_str.contains("value"));
854 assert!(!json_str.contains("\n")); }
856
857 #[test]
858 fn test_duplicate() {
859 let original = CJson::create_string("test").unwrap();
860 let duplicate = original.duplicate(true).unwrap();
861
862 assert_eq!(
863 original.get_string_value().unwrap(),
864 duplicate.get_string_value().unwrap()
865 );
866 }
867
868 #[test]
869 fn test_compare() {
870 let json1 = CJson::create_number(42.0).unwrap();
871 let json2 = CJson::create_number(42.0).unwrap();
872 let json3 = CJson::create_number(43.0).unwrap();
873
874 assert!(json1.compare(&json2, true));
875 assert!(!json1.compare(&json3, true));
876 }
877
878 #[test]
879 fn test_create_int_array() {
880 let values = [1, 2, 3, 4, 5];
881 let arr = CJson::create_int_array(&values).unwrap();
882
883 assert!(arr.is_array());
884 assert_eq!(arr.get_array_size().unwrap(), 5);
885 }
886
887 #[test]
888 fn test_create_double_array() {
889 let values = [1.1, 2.2, 3.3];
890 let arr = CJson::create_double_array(&values).unwrap();
891
892 assert!(arr.is_array());
893 assert_eq!(arr.get_array_size().unwrap(), 3);
894 }
895
896 #[test]
897 #[ignore] fn test_create_string_array() {
899 let values = ["foo", "bar", "baz"];
900 let arr = CJson::create_string_array(&values).unwrap();
901
902 assert!(arr.is_array());
903 assert_eq!(arr.get_array_size().unwrap(), 3);
904 }
905
906 #[test]
907 fn test_delete_item_from_array() {
908 let mut arr = CJson::create_array().unwrap();
909 arr.add_item_to_array(CJson::create_number(1.0).unwrap()).unwrap();
910 arr.add_item_to_array(CJson::create_number(2.0).unwrap()).unwrap();
911 arr.add_item_to_array(CJson::create_number(3.0).unwrap()).unwrap();
912
913 assert_eq!(arr.get_array_size().unwrap(), 3);
914 arr.delete_item_from_array(1).unwrap();
915 assert_eq!(arr.get_array_size().unwrap(), 2);
916 }
917
918 #[test]
919 fn test_delete_item_from_object() {
920 let mut obj = CJson::create_object().unwrap();
921 obj.add_string_to_object("key1", "value1").unwrap();
922 obj.add_string_to_object("key2", "value2").unwrap();
923
924 assert!(obj.has_object_item("key1"));
925 obj.delete_item_from_object("key1").unwrap();
926 assert!(!obj.has_object_item("key1"));
927 assert!(obj.has_object_item("key2"));
928 }
929
930 #[test]
931 fn test_parse_nested_object() {
932 let json = r#"{"person":{"name":"John","age":30}}"#;
933 let parsed = CJson::parse(json).unwrap();
934
935 let person = parsed.get_object_item("person").unwrap();
936 assert!(person.is_object());
937
938 let name = person.get_object_item("name").unwrap();
939 assert_eq!(name.get_string_value().unwrap(), "John");
940 }
941
942 #[test]
943 fn test_type_error() {
944 let json = CJson::create_string("not a number").unwrap();
945 assert!(json.get_number_value().is_err());
946 }
947
948 #[test]
949 fn test_not_found_error() {
950 let obj = CJson::create_object().unwrap();
951 assert!(obj.get_object_item("nonexistent").is_err());
952 }
953
954 #[test]
955 fn test_parse_with_length() {
956 let json = r#"{"key":"value"}"#;
957 let parsed = CJson::parse_with_length(json, json.len()).unwrap();
958 assert!(parsed.is_object());
959 }
960
961 #[test]
962 fn test_case_sensitive_get() {
963 let mut obj = CJson::create_object().unwrap();
964 obj.add_string_to_object("Key", "value").unwrap();
965
966 assert!(obj.get_object_item_case_sensitive("Key").is_ok());
967 assert!(obj.get_object_item_case_sensitive("key").is_err());
968 }
969}