1pub mod literal;
2pub mod string;
3pub mod validation;
4
5use indexmap::IndexMap;
6pub use literal::{
7 is_keyword,
8 is_literal_like,
9 is_numeric_like,
10 is_structural_char,
11};
12pub use string::{
13 escape_string,
14 is_valid_unquoted_key,
15 needs_quoting,
16 quote_string,
17 unescape_string,
18};
19
20use crate::types::{
21 JsonValue as Value,
22 Number,
23};
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub enum QuotingContext {
28 Key,
29 Value,
30 Header,
31}
32
33pub fn normalize(value: Value) -> Value {
35 match value {
36 Value::Number(n) => {
37 if let Number::NegInt(0) = n {
39 Value::Number(Number::from(0u64))
40 } else if let Some(f) = n.as_f64() {
41 if f.is_nan() || f.is_infinite() {
42 Value::Null
43 } else if f == 0.0 && f.is_sign_negative() {
44 Value::Number(Number::from(0u64))
45 } else {
46 Value::Number(n)
47 }
48 } else {
49 Value::Number(n)
50 }
51 }
52 Value::Object(obj) => {
53 let normalized: IndexMap<String, Value> =
54 obj.into_iter().map(|(k, v)| (k, normalize(v))).collect();
55 Value::Object(normalized)
56 }
57 Value::Array(arr) => {
58 let normalized: Vec<Value> = arr.into_iter().map(normalize).collect();
59 Value::Array(normalized)
60 }
61 _ => value,
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use core::f64;
68
69 use serde_json::json;
70
71 use super::*;
72
73 #[test]
74 fn test_normalize_nan() {
75 let value = Value::from(json!(f64::NAN));
76 let normalized = normalize(value);
77 assert_eq!(normalized, Value::from(json!(null)));
78 }
79
80 #[test]
81 fn test_normalize_infinity() {
82 let value = Value::from(json!(f64::INFINITY));
83 let normalized = normalize(value);
84 assert_eq!(normalized, Value::from(json!(null)));
85
86 let value = Value::from(json!(f64::NEG_INFINITY));
87 let normalized = normalize(value);
88 assert_eq!(normalized, Value::from(json!(null)));
89 }
90
91 #[test]
92 fn test_normalize_negative_zero() {
93 let value = Value::from(json!(-0.0));
94 let normalized = normalize(value);
95 assert_eq!(normalized, Value::from(json!(0)));
96 }
97
98 #[test]
99 fn test_normalize_nested() {
100 let value = Value::from(json!({
101 "a": f64::NAN,
102 "b": {
103 "c": f64::INFINITY
104 },
105 "d": [1, f64::NAN, 3]
106 }));
107
108 let normalized = normalize(value);
109 assert_eq!(
110 normalized,
111 Value::from(json!({
112 "a": null,
113 "b": {
114 "c": null
115 },
116 "d": [1, null, 3]
117 }))
118 );
119 }
120
121 #[test]
122 fn test_normalize_normal_values() {
123 let value = Value::from(json!({
124 "name": "Alice",
125 "age": 30,
126 "score": f64::consts::PI
127 }));
128
129 let normalized = normalize(value.clone());
130 assert_eq!(normalized, value);
131 }
132}