1extern crate alloc;
6
7use alloc::ffi::CString;
8use alloc::string::String;
9use alloc::vec::Vec;
10use core::ffi::{CStr, c_char, c_int};
11use core::ptr;
12
13use crate::cjson_ffi::*;
14
15pub type CJsonResult<T> = Result<T, CJsonError>;
17
18#[derive(Debug)]
20pub enum CJsonError {
21 ParseError,
23 NullPointer,
25 InvalidUtf8,
27 NotFound,
29 TypeError,
31 AllocationError,
33 InvalidOperation,
35}
36
37pub struct CJson {
39 ptr: *mut cJSON,
40}
41
42impl CJson {
43 pub(crate) unsafe fn from_ptr(ptr: *mut cJSON) -> CJsonResult<Self> {
48 if ptr.is_null() {
49 Err(CJsonError::NullPointer)
50 } else {
51 Ok(CJson { ptr })
52 }
53 }
54
55 pub fn as_ptr(&self) -> *const cJSON {
57 self.ptr
58 }
59
60 pub fn as_mut_ptr(&mut self) -> *mut cJSON {
62 self.ptr
63 }
64
65 pub fn into_raw(self) -> *mut cJSON {
67 let ptr = self.ptr;
68 core::mem::forget(self);
69 ptr
70 }
71
72 pub fn parse(json: &str) -> CJsonResult<Self> {
78 let c_str = CString::new(json).map_err(|_| CJsonError::InvalidUtf8)?;
79 let ptr = unsafe { cJSON_Parse(c_str.as_ptr()) };
80 unsafe { Self::from_ptr(ptr) }
81 }
82
83 pub fn parse_with_length(json: &str, length: usize) -> CJsonResult<Self> {
85 let c_str = CString::new(json).map_err(|_| CJsonError::InvalidUtf8)?;
86 let ptr = unsafe { cJSON_ParseWithLength(c_str.as_ptr(), length) };
87 unsafe { Self::from_ptr(ptr) }
88 }
89
90 pub fn parse_with_opts(json: &str, require_null_terminated: bool) -> CJsonResult<Self> {
92 let c_str = CString::new(json).map_err(|_| CJsonError::InvalidUtf8)?;
93 let ptr = unsafe {
94 cJSON_ParseWithOpts(
95 c_str.as_ptr(),
96 ptr::null_mut(),
97 if require_null_terminated { 1 } else { 0 },
98 )
99 };
100 unsafe { Self::from_ptr(ptr) }
101 }
102
103 pub fn print(&self) -> CJsonResult<String> {
109 let c_str = unsafe { cJSON_Print(self.ptr) };
110 if c_str.is_null() {
111 return Err(CJsonError::AllocationError);
112 }
113 let rust_str = unsafe { CStr::from_ptr(c_str).to_string_lossy().into_owned() };
114 unsafe { cJSON_free(c_str as *mut core::ffi::c_void) };
115 Ok(rust_str)
116 }
117
118 pub fn print_unformatted(&self) -> CJsonResult<String> {
120 let c_str = unsafe { cJSON_PrintUnformatted(self.ptr) };
121 if c_str.is_null() {
122 return Err(CJsonError::AllocationError);
123 }
124 let rust_str = unsafe { CStr::from_ptr(c_str).to_string_lossy().into_owned() };
125 unsafe { cJSON_free(c_str as *mut core::ffi::c_void) };
126 Ok(rust_str)
127 }
128
129 pub fn is_invalid(&self) -> bool {
135 unsafe { cJSON_IsInvalid(self.ptr) != 0 }
136 }
137
138 pub fn is_false(&self) -> bool {
140 unsafe { cJSON_IsFalse(self.ptr) != 0 }
141 }
142
143 pub fn is_true(&self) -> bool {
145 unsafe { cJSON_IsTrue(self.ptr) != 0 }
146 }
147
148 pub fn is_bool(&self) -> bool {
150 unsafe { cJSON_IsBool(self.ptr) != 0 }
151 }
152
153 pub fn is_null(&self) -> bool {
155 unsafe { cJSON_IsNull(self.ptr) != 0 }
156 }
157
158 pub fn is_number(&self) -> bool {
160 unsafe { cJSON_IsNumber(self.ptr) != 0 }
161 }
162
163 pub fn is_string(&self) -> bool {
165 unsafe { cJSON_IsString(self.ptr) != 0 }
166 }
167
168 pub fn is_array(&self) -> bool {
170 unsafe { cJSON_IsArray(self.ptr) != 0 }
171 }
172
173 pub fn is_object(&self) -> bool {
175 unsafe { cJSON_IsObject(self.ptr) != 0 }
176 }
177
178 pub fn is_raw(&self) -> bool {
180 unsafe { cJSON_IsRaw(self.ptr) != 0 }
181 }
182
183 pub fn get_string_value(&self) -> CJsonResult<String> {
189 if !self.is_string() {
190 return Err(CJsonError::TypeError);
191 }
192 let c_str = unsafe { cJSON_GetStringValue(self.ptr) };
193 if c_str.is_null() {
194 return Err(CJsonError::NullPointer);
195 }
196 Ok(unsafe { CStr::from_ptr(c_str).to_string_lossy().into_owned() })
197 }
198
199 pub fn get_number_value(&self) -> CJsonResult<f64> {
201 if !self.is_number() {
202 return Err(CJsonError::TypeError);
203 }
204 Ok(unsafe { cJSON_GetNumberValue(self.ptr) })
205 }
206
207 pub fn get_int_value(&self) -> CJsonResult<i32> {
209 if !self.is_number() {
210 return Err(CJsonError::TypeError);
211 }
212 Ok(unsafe { (*self.ptr).valueint })
213 }
214
215 pub fn get_bool_value(&self) -> CJsonResult<bool> {
217 if !self.is_bool() {
218 return Err(CJsonError::TypeError);
219 }
220 Ok(self.is_true())
221 }
222
223 pub fn get_array_size(&self) -> CJsonResult<usize> {
229 if !self.is_array() {
230 return Err(CJsonError::TypeError);
231 }
232 Ok(unsafe { cJSON_GetArraySize(self.ptr) as usize })
233 }
234
235 pub fn get_array_item(&self, index: usize) -> CJsonResult<CJsonRef> {
237 if !self.is_array() {
238 return Err(CJsonError::TypeError);
239 }
240 let ptr = unsafe { cJSON_GetArrayItem(self.ptr, index as c_int) };
241 unsafe { CJsonRef::from_ptr(ptr) }.map_err(|_| CJsonError::NotFound)
242 }
243
244 pub fn get_object_item(&self, key: &str) -> CJsonResult<CJsonRef> {
250 if !self.is_object() {
251 return Err(CJsonError::TypeError);
252 }
253 let c_key = CString::new(key).map_err(|_| CJsonError::InvalidUtf8)?;
254 let ptr = unsafe { cJSON_GetObjectItem(self.ptr, c_key.as_ptr()) };
255 unsafe { CJsonRef::from_ptr(ptr) }.map_err(|_| CJsonError::NotFound)
256 }
257
258 pub fn get_object_item_case_sensitive(&self, key: &str) -> CJsonResult<CJsonRef> {
260 if !self.is_object() {
261 return Err(CJsonError::TypeError);
262 }
263 let c_key = CString::new(key).map_err(|_| CJsonError::InvalidUtf8)?;
264 let ptr = unsafe { cJSON_GetObjectItemCaseSensitive(self.ptr, c_key.as_ptr()) };
265 unsafe { CJsonRef::from_ptr(ptr) }.map_err(|_| CJsonError::NotFound)
266 }
267
268 pub fn has_object_item(&self, key: &str) -> bool {
270 if !self.is_object() {
271 return false;
272 }
273 let Ok(c_key) = CString::new(key) else {
274 return false;
275 };
276 unsafe { cJSON_HasObjectItem(self.ptr, c_key.as_ptr()) != 0 }
277 }
278
279 pub fn create_null() -> CJsonResult<Self> {
285 let ptr = unsafe { cJSON_CreateNull() };
286 unsafe { Self::from_ptr(ptr) }
287 }
288
289 pub fn create_true() -> CJsonResult<Self> {
291 let ptr = unsafe { cJSON_CreateTrue() };
292 unsafe { Self::from_ptr(ptr) }
293 }
294
295 pub fn create_false() -> CJsonResult<Self> {
297 let ptr = unsafe { cJSON_CreateFalse() };
298 unsafe { Self::from_ptr(ptr) }
299 }
300
301 pub fn create_bool(value: bool) -> CJsonResult<Self> {
303 let ptr = unsafe { cJSON_CreateBool(if value { 1 } else { 0 }) };
304 unsafe { Self::from_ptr(ptr) }
305 }
306
307 pub fn create_number(value: f64) -> CJsonResult<Self> {
309 let ptr = unsafe { cJSON_CreateNumber(value) };
310 unsafe { Self::from_ptr(ptr) }
311 }
312
313 pub fn create_string(value: &str) -> CJsonResult<Self> {
315 let c_str = CString::new(value).map_err(|_| CJsonError::InvalidUtf8)?;
316 let ptr = unsafe { cJSON_CreateString(c_str.as_ptr()) };
317 unsafe { Self::from_ptr(ptr) }
318 }
319
320 pub fn create_array() -> CJsonResult<Self> {
322 let ptr = unsafe { cJSON_CreateArray() };
323 unsafe { Self::from_ptr(ptr) }
324 }
325
326 pub fn create_object() -> CJsonResult<Self> {
328 let ptr = unsafe { cJSON_CreateObject() };
329 unsafe { Self::from_ptr(ptr) }
330 }
331
332 pub fn create_int_array(values: &[i32]) -> CJsonResult<Self> {
334 let ptr = unsafe { cJSON_CreateIntArray(values.as_ptr(), values.len() as c_int) };
335 unsafe { Self::from_ptr(ptr) }
336 }
337
338 pub fn create_double_array(values: &[f64]) -> CJsonResult<Self> {
340 let ptr = unsafe { cJSON_CreateDoubleArray(values.as_ptr(), values.len() as c_int) };
341 unsafe { Self::from_ptr(ptr) }
342 }
343
344 pub fn create_string_array(values: &[&str]) -> CJsonResult<Self> {
346 let c_strings: Vec<CString> = values
347 .iter()
348 .map(|s| CString::new(*s))
349 .collect::<Result<_, _>>()
350 .map_err(|_| CJsonError::InvalidUtf8)?;
351
352 let c_ptrs: Vec<*const c_char> = c_strings.iter().map(|s| s.as_ptr()).collect();
353
354 let ptr = unsafe { cJSON_CreateStringArray(c_ptrs.as_ptr(), c_ptrs.len() as c_int) };
355 unsafe { Self::from_ptr(ptr) }
356 }
357
358 pub fn add_item_to_array(&mut self, item: CJson) -> CJsonResult<()> {
364 if !self.is_array() {
365 return Err(CJsonError::TypeError);
366 }
367 let result = unsafe { cJSON_AddItemToArray(self.ptr, item.into_raw()) };
368 if result != 0 {
369 Ok(())
370 } else {
371 Err(CJsonError::InvalidOperation)
372 }
373 }
374
375 pub fn delete_item_from_array(&mut self, index: usize) -> CJsonResult<()> {
377 if !self.is_array() {
378 return Err(CJsonError::TypeError);
379 }
380 unsafe { cJSON_DeleteItemFromArray(self.ptr, index as c_int) };
381 Ok(())
382 }
383
384 pub fn detach_item_from_array(&mut self, index: usize) -> CJsonResult<CJson> {
386 if !self.is_array() {
387 return Err(CJsonError::TypeError);
388 }
389 let ptr = unsafe { cJSON_DetachItemFromArray(self.ptr, index as c_int) };
390 unsafe { Self::from_ptr(ptr) }
391 }
392
393 pub fn add_item_to_object(&mut self, key: &str, item: CJson) -> CJsonResult<()> {
399 if !self.is_object() {
400 return Err(CJsonError::TypeError);
401 }
402 let c_key = CString::new(key).map_err(|_| CJsonError::InvalidUtf8)?;
403 let result = unsafe { cJSON_AddItemToObject(self.ptr, c_key.as_ptr(), item.into_raw()) };
404 if result != 0 {
405 Ok(())
406 } else {
407 Err(CJsonError::InvalidOperation)
408 }
409 }
410
411 pub fn add_null_to_object(&mut self, key: &str) -> CJsonResult<()> {
413 if !self.is_object() {
414 return Err(CJsonError::TypeError);
415 }
416 let c_key = CString::new(key).map_err(|_| CJsonError::InvalidUtf8)?;
417 let ptr = unsafe { cJSON_AddNullToObject(self.ptr, c_key.as_ptr()) };
418 if ptr.is_null() {
419 Err(CJsonError::AllocationError)
420 } else {
421 Ok(())
422 }
423 }
424
425 pub fn add_true_to_object(&mut self, key: &str) -> CJsonResult<()> {
427 if !self.is_object() {
428 return Err(CJsonError::TypeError);
429 }
430 let c_key = CString::new(key).map_err(|_| CJsonError::InvalidUtf8)?;
431 let ptr = unsafe { cJSON_AddTrueToObject(self.ptr, c_key.as_ptr()) };
432 if ptr.is_null() {
433 Err(CJsonError::AllocationError)
434 } else {
435 Ok(())
436 }
437 }
438
439 pub fn add_false_to_object(&mut self, key: &str) -> CJsonResult<()> {
441 if !self.is_object() {
442 return Err(CJsonError::TypeError);
443 }
444 let c_key = CString::new(key).map_err(|_| CJsonError::InvalidUtf8)?;
445 let ptr = unsafe { cJSON_AddFalseToObject(self.ptr, c_key.as_ptr()) };
446 if ptr.is_null() {
447 Err(CJsonError::AllocationError)
448 } else {
449 Ok(())
450 }
451 }
452
453 pub fn add_bool_to_object(&mut self, key: &str, value: bool) -> CJsonResult<()> {
455 if !self.is_object() {
456 return Err(CJsonError::TypeError);
457 }
458 let c_key = CString::new(key).map_err(|_| CJsonError::InvalidUtf8)?;
459 let ptr = unsafe {
460 cJSON_AddBoolToObject(self.ptr, c_key.as_ptr(), if value { 1 } else { 0 })
461 };
462 if ptr.is_null() {
463 Err(CJsonError::AllocationError)
464 } else {
465 Ok(())
466 }
467 }
468
469 pub fn add_number_to_object(&mut self, key: &str, value: f64) -> CJsonResult<()> {
471 if !self.is_object() {
472 return Err(CJsonError::TypeError);
473 }
474 let c_key = CString::new(key).map_err(|_| CJsonError::InvalidUtf8)?;
475 let ptr = unsafe { cJSON_AddNumberToObject(self.ptr, c_key.as_ptr(), value) };
476 if ptr.is_null() {
477 Err(CJsonError::AllocationError)
478 } else {
479 Ok(())
480 }
481 }
482
483 pub fn add_string_to_object(&mut self, key: &str, value: &str) -> CJsonResult<()> {
485 if !self.is_object() {
486 return Err(CJsonError::TypeError);
487 }
488 let c_key = CString::new(key).map_err(|_| CJsonError::InvalidUtf8)?;
489 let c_value = CString::new(value).map_err(|_| CJsonError::InvalidUtf8)?;
490 let ptr = unsafe { cJSON_AddStringToObject(self.ptr, c_key.as_ptr(), c_value.as_ptr()) };
491 if ptr.is_null() {
492 Err(CJsonError::AllocationError)
493 } else {
494 Ok(())
495 }
496 }
497
498 pub fn delete_item_from_object(&mut self, key: &str) -> CJsonResult<()> {
500 if !self.is_object() {
501 return Err(CJsonError::TypeError);
502 }
503 let c_key = CString::new(key).map_err(|_| CJsonError::InvalidUtf8)?;
504 unsafe { cJSON_DeleteItemFromObject(self.ptr, c_key.as_ptr()) };
505 Ok(())
506 }
507
508 pub fn detach_item_from_object(&mut self, key: &str) -> CJsonResult<CJson> {
510 if !self.is_object() {
511 return Err(CJsonError::TypeError);
512 }
513 let c_key = CString::new(key).map_err(|_| CJsonError::InvalidUtf8)?;
514 let ptr = unsafe { cJSON_DetachItemFromObject(self.ptr, c_key.as_ptr()) };
515 unsafe { Self::from_ptr(ptr) }
516 }
517
518 pub fn duplicate(&self, recurse: bool) -> CJsonResult<Self> {
524 let ptr = unsafe { cJSON_Duplicate(self.ptr, if recurse { 1 } else { 0 }) };
525 unsafe { Self::from_ptr(ptr) }
526 }
527
528 pub fn compare(&self, other: &CJson, case_sensitive: bool) -> bool {
530 unsafe {
531 cJSON_Compare(self.ptr, other.ptr, if case_sensitive { 1 } else { 0 }) != 0
532 }
533 }
534}
535
536impl Drop for CJson {
537 fn drop(&mut self) {
538 if !self.ptr.is_null() {
539 unsafe { cJSON_Delete(self.ptr) };
540 }
541 }
542}
543
544pub struct CJsonRef {
546 ptr: *mut cJSON,
547}
548
549impl CJsonRef {
550 pub(crate) unsafe fn from_ptr(ptr: *mut cJSON) -> CJsonResult<Self> {
555 if ptr.is_null() {
556 Err(CJsonError::NullPointer)
557 } else {
558 Ok(CJsonRef { ptr })
559 }
560 }
561
562 pub fn as_ptr(&self) -> *const cJSON {
564 self.ptr
565 }
566
567 pub fn is_string(&self) -> bool {
569 unsafe { cJSON_IsString(self.ptr) != 0 }
570 }
571
572 pub fn is_number(&self) -> bool {
574 unsafe { cJSON_IsNumber(self.ptr) != 0 }
575 }
576
577 pub fn is_bool(&self) -> bool {
579 unsafe { cJSON_IsBool(self.ptr) != 0 }
580 }
581
582 pub fn is_null(&self) -> bool {
584 unsafe { cJSON_IsNull(self.ptr) != 0 }
585 }
586
587 pub fn is_array(&self) -> bool {
589 unsafe { cJSON_IsArray(self.ptr) != 0 }
590 }
591
592 pub fn is_object(&self) -> bool {
594 unsafe { cJSON_IsObject(self.ptr) != 0 }
595 }
596
597 pub fn get_string_value(&self) -> CJsonResult<String> {
599 if !self.is_string() {
600 return Err(CJsonError::TypeError);
601 }
602 let c_str = unsafe { cJSON_GetStringValue(self.ptr) };
603 if c_str.is_null() {
604 return Err(CJsonError::NullPointer);
605 }
606 Ok(unsafe { CStr::from_ptr(c_str).to_string_lossy().into_owned() })
607 }
608
609 pub fn get_number_value(&self) -> CJsonResult<f64> {
611 if !self.is_number() {
612 return Err(CJsonError::TypeError);
613 }
614 Ok(unsafe { cJSON_GetNumberValue(self.ptr) })
615 }
616
617 pub fn get_int_value(&self) -> CJsonResult<i32> {
619 if !self.is_number() {
620 return Err(CJsonError::TypeError);
621 }
622 Ok(unsafe { (*self.ptr).valueint })
623 }
624
625 pub fn get_bool_value(&self) -> CJsonResult<bool> {
627 if !self.is_bool() {
628 return Err(CJsonError::TypeError);
629 }
630 Ok(unsafe { cJSON_IsTrue(self.ptr) != 0 })
631 }
632
633 pub fn get_array_size(&self) -> CJsonResult<usize> {
635 if !self.is_array() {
636 return Err(CJsonError::TypeError);
637 }
638 Ok(unsafe { cJSON_GetArraySize(self.ptr) as usize })
639 }
640
641 pub fn get_array_item(&self, index: usize) -> CJsonResult<CJsonRef> {
643 if !self.is_array() {
644 return Err(CJsonError::TypeError);
645 }
646 let ptr = unsafe { cJSON_GetArrayItem(self.ptr, index as c_int) };
647 unsafe { CJsonRef::from_ptr(ptr) }.map_err(|_| CJsonError::NotFound)
648 }
649
650 pub fn get_object_item(&self, key: &str) -> CJsonResult<CJsonRef> {
652 if !self.is_object() {
653 return Err(CJsonError::TypeError);
654 }
655 let c_key = CString::new(key).map_err(|_| CJsonError::InvalidUtf8)?;
656 let ptr = unsafe { cJSON_GetObjectItem(self.ptr, c_key.as_ptr()) };
657 unsafe { CJsonRef::from_ptr(ptr) }.map_err(|_| CJsonError::NotFound)
658 }
659}
660
661#[allow(dead_code)]
663pub fn version() -> String {
664 let c_str = unsafe { cJSON_Version() };
665 unsafe { CStr::from_ptr(c_str).to_string_lossy().into_owned() }
666}
667
668#[allow(dead_code)]
670pub fn get_error_ptr() -> Option<String> {
671 let c_str = unsafe { cJSON_GetErrorPtr() };
672 if c_str.is_null() {
673 None
674 } else {
675 Some(unsafe { CStr::from_ptr(c_str).to_string_lossy().into_owned() })
676 }
677}
678
679#[allow(dead_code)]
681pub fn minify(json: &mut String) {
682 let c_str = CString::new(json.as_str()).expect("CString conversion failed");
683 unsafe {
684 let ptr = c_str.as_ptr() as *mut c_char;
685 cJSON_Minify(ptr);
686 *json = CStr::from_ptr(ptr).to_string_lossy().into_owned();
687 }
688}
689
690#[cfg(test)]
691mod tests {
692 use super::*;
693
694 #[test]
695 fn test_parse_simple_object() {
696 let json = r#"{"name":"John","age":30}"#;
697 let parsed = CJson::parse(json).unwrap();
698 assert!(parsed.is_object());
699 }
700
701 #[test]
702 fn test_parse_array() {
703 let json = r#"[1,2,3,4,5]"#;
704 let parsed = CJson::parse(json).unwrap();
705 assert!(parsed.is_array());
706 assert_eq!(parsed.get_array_size().unwrap(), 5);
707 }
708
709 #[test]
710 fn test_create_and_get_string() {
711 let json = CJson::create_string("Hello, World!").unwrap();
712 assert!(json.is_string());
713 assert_eq!(json.get_string_value().unwrap(), "Hello, World!");
714 }
715
716 #[test]
717 fn test_create_and_get_number() {
718 let json = CJson::create_number(42.5).unwrap();
719 assert!(json.is_number());
720 assert_eq!(json.get_number_value().unwrap(), 42.5);
721 }
722
723 #[test]
724 fn test_create_and_get_bool() {
725 let json_true = CJson::create_true().unwrap();
726 assert!(json_true.is_true());
727 assert!(json_true.is_bool());
728 assert_eq!(json_true.get_bool_value().unwrap(), true);
729
730 let json_false = CJson::create_false().unwrap();
731 assert!(json_false.is_false());
732 assert!(json_false.is_bool());
733 assert_eq!(json_false.get_bool_value().unwrap(), false);
734 }
735
736 #[test]
737 fn test_create_null() {
738 let json = CJson::create_null().unwrap();
739 assert!(json.is_null());
740 }
741
742 #[test]
743 fn test_create_object_and_add_items() {
744 let mut obj = CJson::create_object().unwrap();
745 obj.add_string_to_object("name", "Alice").unwrap();
746 obj.add_number_to_object("age", 25.0).unwrap();
747 obj.add_bool_to_object("active", true).unwrap();
748
749 assert!(obj.is_object());
750 assert!(obj.has_object_item("name"));
751 assert!(obj.has_object_item("age"));
752 assert!(obj.has_object_item("active"));
753
754 let name = obj.get_object_item("name").unwrap();
755 assert_eq!(name.get_string_value().unwrap(), "Alice");
756
757 let age = obj.get_object_item("age").unwrap();
758 assert_eq!(age.get_number_value().unwrap(), 25.0);
759 }
760
761 #[test]
762 fn test_create_array_and_add_items() {
763 let mut arr = CJson::create_array().unwrap();
764 arr.add_item_to_array(CJson::create_number(1.0).unwrap()).unwrap();
765 arr.add_item_to_array(CJson::create_number(2.0).unwrap()).unwrap();
766 arr.add_item_to_array(CJson::create_number(3.0).unwrap()).unwrap();
767
768 assert!(arr.is_array());
769 assert_eq!(arr.get_array_size().unwrap(), 3);
770
771 let item = arr.get_array_item(1).unwrap();
772 assert_eq!(item.get_number_value().unwrap(), 2.0);
773 }
774
775 #[test]
776 fn test_print_formatted() {
777 let mut obj = CJson::create_object().unwrap();
778 obj.add_string_to_object("key", "value").unwrap();
779
780 let json_str = obj.print().unwrap();
781 assert!(json_str.contains("key"));
782 assert!(json_str.contains("value"));
783 }
784
785 #[test]
786 fn test_print_unformatted() {
787 let mut obj = CJson::create_object().unwrap();
788 obj.add_string_to_object("key", "value").unwrap();
789
790 let json_str = obj.print_unformatted().unwrap();
791 assert!(json_str.contains("key"));
792 assert!(json_str.contains("value"));
793 assert!(!json_str.contains("\n")); }
795
796 #[test]
797 fn test_duplicate() {
798 let original = CJson::create_string("test").unwrap();
799 let duplicate = original.duplicate(true).unwrap();
800
801 assert_eq!(
802 original.get_string_value().unwrap(),
803 duplicate.get_string_value().unwrap()
804 );
805 }
806
807 #[test]
808 fn test_compare() {
809 let json1 = CJson::create_number(42.0).unwrap();
810 let json2 = CJson::create_number(42.0).unwrap();
811 let json3 = CJson::create_number(43.0).unwrap();
812
813 assert!(json1.compare(&json2, true));
814 assert!(!json1.compare(&json3, true));
815 }
816
817 #[test]
818 fn test_create_int_array() {
819 let values = [1, 2, 3, 4, 5];
820 let arr = CJson::create_int_array(&values).unwrap();
821
822 assert!(arr.is_array());
823 assert_eq!(arr.get_array_size().unwrap(), 5);
824 }
825
826 #[test]
827 fn test_create_double_array() {
828 let values = [1.1, 2.2, 3.3];
829 let arr = CJson::create_double_array(&values).unwrap();
830
831 assert!(arr.is_array());
832 assert_eq!(arr.get_array_size().unwrap(), 3);
833 }
834
835 #[test]
836 #[ignore] fn test_create_string_array() {
838 let values = ["foo", "bar", "baz"];
839 let arr = CJson::create_string_array(&values).unwrap();
840
841 assert!(arr.is_array());
842 assert_eq!(arr.get_array_size().unwrap(), 3);
843 }
844
845 #[test]
846 fn test_delete_item_from_array() {
847 let mut arr = CJson::create_array().unwrap();
848 arr.add_item_to_array(CJson::create_number(1.0).unwrap()).unwrap();
849 arr.add_item_to_array(CJson::create_number(2.0).unwrap()).unwrap();
850 arr.add_item_to_array(CJson::create_number(3.0).unwrap()).unwrap();
851
852 assert_eq!(arr.get_array_size().unwrap(), 3);
853 arr.delete_item_from_array(1).unwrap();
854 assert_eq!(arr.get_array_size().unwrap(), 2);
855 }
856
857 #[test]
858 fn test_delete_item_from_object() {
859 let mut obj = CJson::create_object().unwrap();
860 obj.add_string_to_object("key1", "value1").unwrap();
861 obj.add_string_to_object("key2", "value2").unwrap();
862
863 assert!(obj.has_object_item("key1"));
864 obj.delete_item_from_object("key1").unwrap();
865 assert!(!obj.has_object_item("key1"));
866 assert!(obj.has_object_item("key2"));
867 }
868
869 #[test]
870 fn test_parse_nested_object() {
871 let json = r#"{"person":{"name":"John","age":30}}"#;
872 let parsed = CJson::parse(json).unwrap();
873
874 let person = parsed.get_object_item("person").unwrap();
875 assert!(person.is_object());
876
877 let name = person.get_object_item("name").unwrap();
878 assert_eq!(name.get_string_value().unwrap(), "John");
879 }
880
881 #[test]
882 fn test_type_error() {
883 let json = CJson::create_string("not a number").unwrap();
884 assert!(json.get_number_value().is_err());
885 }
886
887 #[test]
888 fn test_not_found_error() {
889 let obj = CJson::create_object().unwrap();
890 assert!(obj.get_object_item("nonexistent").is_err());
891 }
892
893 #[test]
894 fn test_parse_with_length() {
895 let json = r#"{"key":"value"}"#;
896 let parsed = CJson::parse_with_length(json, json.len()).unwrap();
897 assert!(parsed.is_object());
898 }
899
900 #[test]
901 fn test_case_sensitive_get() {
902 let mut obj = CJson::create_object().unwrap();
903 obj.add_string_to_object("Key", "value").unwrap();
904
905 assert!(obj.get_object_item_case_sensitive("Key").is_ok());
906 assert!(obj.get_object_item_case_sensitive("key").is_err());
907 }
908}