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