json_eval_rs/jsoneval/
getters.rs1use super::JSONEval;
2use crate::jsoneval::path_utils;
3use crate::jsoneval::types::ReturnFormat;
4
5
6
7use serde_json::Value;
8use crate::time_block;
9
10
11impl JSONEval {
12 pub fn get_evaluated_schema(&mut self, skip_layout: bool) -> Value {
22 time_block!("get_evaluated_schema()", {
23 if !skip_layout {
24 if let Err(e) = self.resolve_layout(false) {
25 eprintln!("Warning: Layout resolution failed in get_evaluated_schema: {}", e);
26 }
27 }
28 self.evaluated_schema.clone()
29 })
30 }
31
32
33
34 pub fn get_schema_value_by_path(&self, path: &str) -> Option<Value> {
36 let pointer_path = path_utils::dot_notation_to_schema_pointer(path);
37 self.evaluated_schema.pointer(&pointer_path).cloned()
38 }
39
40 pub fn get_schema_value(&mut self) -> Value {
44 let mut current_data = self.eval_data.data().clone();
46
47 if !current_data.is_object() {
49 current_data = Value::Object(serde_json::Map::new());
50 }
51
52 for eval_key in self.value_evaluations.iter() {
55 let clean_key = eval_key.replace('#', "");
56
57 if clean_key.starts_with("/$params")
59 || (clean_key.ends_with("/value")
60 && (clean_key.contains("/rules/") || clean_key.contains("/options/")))
61 {
62 continue;
63 }
64
65 let path = clean_key.replace("/properties", "").replace("/value", "");
66
67 let value = match self.evaluated_schema.pointer(&clean_key) {
69 Some(v) => v.clone(),
70 None => continue,
71 };
72
73 let path_parts: Vec<&str> = path.split('/').filter(|s| !s.is_empty()).collect();
75
76 if path_parts.is_empty() {
77 continue;
78 }
79
80 let mut current = &mut current_data;
82 for (i, part) in path_parts.iter().enumerate() {
83 let is_last = i == path_parts.len() - 1;
84
85 if is_last {
86 if let Some(obj) = current.as_object_mut() {
88 obj.insert(part.to_string(), crate::utils::clean_float_noise(value.clone()));
89 }
90 } else {
91 if let Some(obj) = current.as_object_mut() {
93 if !obj.contains_key(*part) {
99 obj.insert((*part).to_string(), Value::Object(serde_json::Map::new()));
100 }
101
102 current = obj.get_mut(*part).unwrap();
103 } else {
104 break;
106 }
107 }
108 }
109 }
110
111 self.data = current_data.clone();
113
114 crate::utils::clean_float_noise(current_data)
115 }
116
117 pub fn get_schema_value_array(&self) -> Value {
124 let mut result = Vec::new();
125
126 for eval_key in self.value_evaluations.iter() {
127 let clean_key = eval_key.replace('#', "");
128
129 if clean_key.starts_with("/$params")
131 || (clean_key.ends_with("/value")
132 && (clean_key.contains("/rules/") || clean_key.contains("/options/")))
133 {
134 continue;
135 }
136
137 let dotted_path = clean_key
139 .replace("/properties", "")
140 .replace("/value", "")
141 .trim_start_matches('/')
142 .replace('/', ".");
143
144 if dotted_path.is_empty() {
145 continue;
146 }
147
148 let value = match self.evaluated_schema.pointer(&clean_key) {
150 Some(v) => crate::utils::clean_float_noise(v.clone()),
151 None => continue,
152 };
153
154 let mut item = serde_json::Map::new();
156 item.insert("path".to_string(), Value::String(dotted_path));
157 item.insert("value".to_string(), value);
158 result.push(Value::Object(item));
159 }
160
161 Value::Array(result)
162 }
163
164 pub fn get_schema_value_object(&self) -> Value {
171 let mut result = serde_json::Map::new();
172
173 for eval_key in self.value_evaluations.iter() {
174 let clean_key = eval_key.replace('#', "");
175
176 if clean_key.starts_with("/$params")
178 || (clean_key.ends_with("/value")
179 && (clean_key.contains("/rules/") || clean_key.contains("/options/")))
180 {
181 continue;
182 }
183
184 let dotted_path = clean_key
186 .replace("/properties", "")
187 .replace("/value", "")
188 .trim_start_matches('/')
189 .replace('/', ".");
190
191 if dotted_path.is_empty() {
192 continue;
193 }
194
195 let value = match self.evaluated_schema.pointer(&clean_key) {
197 Some(v) => crate::utils::clean_float_noise(v.clone()),
198 None => continue,
199 };
200
201 result.insert(dotted_path, value);
202 }
203
204 Value::Object(result)
205 }
206
207 pub fn get_evaluated_schema_without_params(&mut self, skip_layout: bool) -> Value {
209 let mut schema = self.get_evaluated_schema(skip_layout);
210 if let Value::Object(ref mut map) = schema {
211 map.remove("$params");
212 }
213 schema
214 }
215
216 pub fn get_evaluated_schema_msgpack(&mut self, skip_layout: bool) -> Result<Vec<u8>, String> {
218 let schema = self.get_evaluated_schema(skip_layout);
219 rmp_serde::to_vec(&schema).map_err(|e| format!("MessagePack serialization failed: {}", e))
220 }
221
222 pub fn get_evaluated_schema_by_path(&mut self, path: &str, skip_layout: bool) -> Option<Value> {
224 if !skip_layout {
225 if let Err(e) = self.resolve_layout(false) {
226 eprintln!("Warning: Layout resolution failed in get_evaluated_schema_by_path: {}", e);
227 }
228 }
229 self.get_schema_value_by_path(path)
230 }
231
232 pub fn get_evaluated_schema_by_paths(
234 &mut self,
235 paths: &[String],
236 skip_layout: bool,
237 format: Option<ReturnFormat>,
238 ) -> Value {
239 if !skip_layout {
240 if let Err(e) = self.resolve_layout(false) {
241 eprintln!("Warning: Layout resolution failed in get_evaluated_schema_by_paths: {}", e);
242 }
243 }
244
245 match format.unwrap_or(ReturnFormat::Nested) {
246 ReturnFormat::Nested => {
247 let mut result = Value::Object(serde_json::Map::new());
248 for path in paths {
249 if let Some(val) = self.get_schema_value_by_path(path) {
250 Self::insert_at_path(&mut result, path, val);
252 }
253 }
254 result
255 }
256 ReturnFormat::Flat => {
257 let mut result = serde_json::Map::new();
258 for path in paths {
259 if let Some(val) = self.get_schema_value_by_path(path) {
260 result.insert(path.clone(), val);
261 }
262 }
263 Value::Object(result)
264 }
265 ReturnFormat::Array => {
266 let mut result = Vec::new();
267 for path in paths {
268 if let Some(val) = self.get_schema_value_by_path(path) {
269 result.push(val);
270 } else {
271 result.push(Value::Null);
272 }
273 }
274 Value::Array(result)
275 }
276 }
277 }
278
279 pub fn get_schema_by_path(&self, path: &str) -> Option<Value> {
281 let pointer_path = path_utils::dot_notation_to_schema_pointer(path);
282 self.schema.pointer(&pointer_path).cloned()
283 }
284
285 pub fn get_schema_by_paths(
287 &self,
288 paths: &[String],
289 format: Option<ReturnFormat>,
290 ) -> Value {
291 match format.unwrap_or(ReturnFormat::Nested) {
292 ReturnFormat::Nested => {
293 let mut result = Value::Object(serde_json::Map::new());
294 for path in paths {
295 if let Some(val) = self.get_schema_by_path(path) {
296 Self::insert_at_path(&mut result, path, val);
297 }
298 }
299 result
300 }
301 ReturnFormat::Flat => {
302 let mut result = serde_json::Map::new();
303 for path in paths {
304 if let Some(val) = self.get_schema_by_path(path) {
305 result.insert(path.clone(), val);
306 }
307 }
308 Value::Object(result)
309 }
310 ReturnFormat::Array => {
311 let mut result = Vec::new();
312 for path in paths {
313 if let Some(val) = self.get_schema_by_path(path) {
314 result.push(val);
315 } else {
316 result.push(Value::Null);
317 }
318 }
319 Value::Array(result)
320 }
321 }
322 }
323
324 pub(crate) fn insert_at_path(root: &mut Value, path: &str, value: Value) {
326 let parts: Vec<&str> = path.split('.').collect();
327 let mut current = root;
328
329 for (i, part) in parts.iter().enumerate() {
330 if i == parts.len() - 1 {
331 if let Value::Object(map) = current {
333 map.insert(part.to_string(), value);
334 return; }
336 } else {
337 if !current.is_object() {
342 *current = Value::Object(serde_json::Map::new());
343 }
344
345 if let Value::Object(map) = current {
346 if !map.contains_key(*part) {
347 map.insert(part.to_string(), Value::Object(serde_json::Map::new()));
348 }
349 current = map.get_mut(*part).unwrap();
350 }
351 }
352 }
353 }
354
355 pub fn flatten_object(prefix: &str, value: &Value, result: &mut serde_json::Map<String, Value>) {
357 match value {
358 Value::Object(map) => {
359 for (k, v) in map {
360 let new_key = if prefix.is_empty() {
361 k.clone()
362 } else {
363 format!("{}.{}", prefix, k)
364 };
365 Self::flatten_object(&new_key, v, result);
366 }
367 }
368 _ => {
369 result.insert(prefix.to_string(), value.clone());
370 }
371 }
372 }
373
374 pub fn convert_to_format(value: Value, format: ReturnFormat) -> Value {
375 match format {
376 ReturnFormat::Nested => value,
377 ReturnFormat::Flat => {
378 let mut result = serde_json::Map::new();
379 Self::flatten_object("", &value, &mut result);
380 Value::Object(result)
381 }
382 ReturnFormat::Array => {
383 if let Value::Object(map) = value {
387 Value::Array(map.values().cloned().collect())
388 } else if let Value::Array(arr) = value {
389 Value::Array(arr)
390 } else {
391 Value::Array(vec![value])
392 }
393 }
394 }
395 }
396}