json_eval_rs/jsoneval/
getters.rs1use super::JSONEval;
2use crate::jsoneval::path_utils;
3use crate::jsoneval::types::ReturnFormat;
4
5use crate::time_block;
6use serde_json::Value;
7
8impl JSONEval {
9 pub(crate) fn is_effective_hidden(&self, schema_pointer: &str) -> bool {
12 let mut end = schema_pointer.len();
13
14 loop {
15 let current_path = &schema_pointer[..end];
16
17 if let Some(schema_node) = self.evaluated_schema.pointer(current_path) {
18 if let Value::Object(map) = schema_node {
19 if let Some(Value::Object(condition)) = map.get("condition") {
20 if let Some(Value::Bool(true)) = condition.get("hidden") {
21 return true;
22 }
23 }
24
25 if let Some(Value::Object(layout)) = map.get("$layout") {
26 if let Some(Value::Object(hide_layout)) = layout.get("hideLayout") {
27 if let Some(Value::Bool(true)) = hide_layout.get("all") {
28 return true;
29 }
30 }
31 }
32 }
33 }
34
35 if end == 0 {
36 break;
37 }
38
39 match schema_pointer[..end].rfind('/') {
41 Some(0) | None => {
42 end = 0;
43 }
44 Some(last_slash) => {
45 end = last_slash;
46 let parent = &schema_pointer[..end];
47 if parent.ends_with("/properties") {
48 end -= "/properties".len();
49 } else if parent.ends_with("/items") {
50 end -= "/items".len();
51 }
52 }
53 }
54 }
55
56 false
57 }
58
59 fn prune_hidden_values(&self, data: &mut Value, current_path: &str) {
61 if let Value::Object(map) = data {
62 let mut keys_to_remove = Vec::new();
64
65 for (key, value) in map.iter_mut() {
66 if key == "$params" || key == "$context" {
68 continue;
69 }
70
71 let schema_path = if current_path.is_empty() {
75 format!("/properties/{}", key)
76 } else {
77 format!("{}/properties/{}", current_path, key)
78 };
79
80 if self.is_effective_hidden(&schema_path) {
82 keys_to_remove.push(key.clone());
83 } else {
84 if value.is_object() {
86 self.prune_hidden_values(value, &schema_path);
87 }
88 }
89 }
90
91 for key in keys_to_remove {
93 map.remove(&key);
94 }
95 }
96 }
97
98 fn resolve_static_markers_in_value(&self, schema_output: &mut Value) {
104 for (static_key, array_arc) in self.static_arrays.iter() {
105 let schema_path = if static_key.starts_with("/$table") {
107 &static_key["/$table".len()..] } else {
109 static_key.as_str() };
111
112 if let Some(target_val) = schema_output.pointer_mut(schema_path) {
114 *target_val = (**array_arc).clone();
116 }
117 }
118 }
119
120 pub fn get_evaluated_schema(&mut self, skip_layout: bool) -> Value {
131 time_block!("get_evaluated_schema()", {
132 if !skip_layout {
133 if let Err(e) = self.resolve_layout(false) {
134 eprintln!(
135 "Warning: Layout resolution failed in get_evaluated_schema: {}",
136 e
137 );
138 }
139 }
140 let mut schema = self.evaluated_schema.clone();
141 self.resolve_static_markers_in_value(&mut schema);
142 schema
143 })
144 }
145
146 pub fn get_schema_value_by_path(&self, path: &str) -> Option<Value> {
149 let pointer_path = path_utils::dot_notation_to_schema_pointer(path);
150 let val = self
151 .evaluated_schema
152 .pointer(pointer_path.trim_start_matches('#'))?;
153
154 if let Value::Object(map) = val {
157 if let Some(Value::String(static_key)) = map.get("$static_array") {
158 let data_path = static_key.trim_start_matches("/$table");
160 return self.eval_data.data().pointer(data_path).cloned();
161 }
162 }
163
164 Some(val.clone())
165 }
166
167 pub fn get_schema_value(&mut self) -> Value {
171 let mut current_data = self.eval_data.data().clone();
173
174 if !current_data.is_object() {
176 current_data = Value::Object(serde_json::Map::new());
177 }
178
179 if let Some(obj) = current_data.as_object_mut() {
181 obj.remove("$params");
182 obj.remove("$context");
183 }
184
185 self.prune_hidden_values(&mut current_data, "");
187
188 for eval_key in self.value_evaluations.iter() {
191 let clean_key = eval_key.strip_prefix('#').unwrap_or(eval_key);
192
193 if clean_key.starts_with("/$params")
195 || (clean_key.ends_with("/value")
196 && (clean_key.contains("/rules/") || clean_key.contains("/options/")))
197 {
198 continue;
199 }
200
201 let path = clean_key.replace("/properties", "").replace("/value", "");
202
203 let schema_path = clean_key.strip_suffix("/value").unwrap_or(&clean_key);
206 if self.is_effective_hidden(schema_path) {
207 continue;
208 }
209
210 let value = match self.evaluated_schema.pointer(&clean_key) {
212 Some(v) => v.clone(),
213 None => continue,
214 };
215
216 let path_parts: Vec<&str> = path.split('/').filter(|s| !s.is_empty()).collect();
218
219 if path_parts.is_empty() {
220 continue;
221 }
222
223 let mut current = &mut current_data;
225 for (i, part) in path_parts.iter().enumerate() {
226 let is_last = i == path_parts.len() - 1;
227
228 if is_last {
229 if let Some(obj) = current.as_object_mut() {
231 let should_update = match obj.get(*part) {
232 Some(v) => v.is_null(),
233 None => true,
234 };
235
236 if should_update {
237 obj.insert(
238 (*part).to_string(),
239 crate::utils::clean_float_noise(value.clone()),
240 );
241 }
242 }
243 } else {
244 if let Some(obj) = current.as_object_mut() {
246 if !obj.contains_key(*part) {
252 obj.insert((*part).to_string(), Value::Object(serde_json::Map::new()));
253 }
254
255 current = obj.get_mut(*part).unwrap();
256 } else {
257 break;
259 }
260 }
261 }
262 }
263
264 self.data = current_data.clone();
266
267 crate::utils::clean_float_noise(current_data)
268 }
269
270 pub fn get_schema_value_array(&self) -> Value {
277 let mut result = Vec::new();
278
279 for eval_key in self.value_evaluations.iter() {
280 let clean_key = eval_key.strip_prefix('#').unwrap_or(eval_key);
281
282 if clean_key.starts_with("/$params")
284 || (clean_key.ends_with("/value")
285 && (clean_key.contains("/rules/") || clean_key.contains("/options/")))
286 {
287 continue;
288 }
289
290 let schema_path = clean_key.strip_suffix("/value").unwrap_or(&clean_key);
292 if self.is_effective_hidden(schema_path) {
293 continue;
294 }
295
296 let dotted_path = clean_key
298 .replace("/properties", "")
299 .replace("/value", "")
300 .trim_start_matches('/')
301 .replace('/', ".");
302
303 if dotted_path.is_empty() {
304 continue;
305 }
306
307 let value = match self.evaluated_schema.pointer(&clean_key) {
309 Some(v) => crate::utils::clean_float_noise(v.clone()),
310 None => continue,
311 };
312
313 let mut item = serde_json::Map::new();
315 item.insert("path".to_string(), Value::String(dotted_path));
316 item.insert("value".to_string(), value);
317 result.push(Value::Object(item));
318 }
319
320 Value::Array(result)
321 }
322
323 pub fn get_schema_value_object(&self) -> Value {
330 let mut result = serde_json::Map::new();
331
332 for eval_key in self.value_evaluations.iter() {
333 let clean_key = eval_key.strip_prefix('#').unwrap_or(eval_key);
334
335 if clean_key.starts_with("/$params")
337 || (clean_key.ends_with("/value")
338 && (clean_key.contains("/rules/") || clean_key.contains("/options/")))
339 {
340 continue;
341 }
342
343 let schema_path = clean_key.strip_suffix("/value").unwrap_or(&clean_key);
345 if self.is_effective_hidden(schema_path) {
346 continue;
347 }
348
349 let dotted_path = clean_key
351 .replace("/properties", "")
352 .replace("/value", "")
353 .trim_start_matches('/')
354 .replace('/', ".");
355
356 if dotted_path.is_empty() {
357 continue;
358 }
359
360 let value = match self.evaluated_schema.pointer(&clean_key) {
362 Some(v) => crate::utils::clean_float_noise(v.clone()),
363 None => continue,
364 };
365
366 result.insert(dotted_path, value);
367 }
368
369 Value::Object(result)
370 }
371
372 pub fn get_evaluated_schema_without_params(&mut self, skip_layout: bool) -> Value {
374 let mut schema = self.get_evaluated_schema(skip_layout);
375 if let Value::Object(ref mut map) = schema {
376 map.remove("$params");
377 }
378 schema
379 }
380
381 pub fn get_evaluated_schema_msgpack(&mut self, skip_layout: bool) -> Result<Vec<u8>, String> {
383 let schema = self.get_evaluated_schema(skip_layout);
384 rmp_serde::to_vec(&schema).map_err(|e| format!("MessagePack serialization failed: {}", e))
385 }
386
387 pub fn get_evaluated_schema_by_path(&mut self, path: &str, skip_layout: bool) -> Option<Value> {
389 if !skip_layout {
390 if let Err(e) = self.resolve_layout(false) {
391 eprintln!(
392 "Warning: Layout resolution failed in get_evaluated_schema_by_path: {}",
393 e
394 );
395 }
396 }
397 self.get_schema_value_by_path(path)
398 }
399
400 pub fn get_evaluated_schema_by_paths(
402 &mut self,
403 paths: &[String],
404 skip_layout: bool,
405 format: Option<ReturnFormat>,
406 ) -> Value {
407 if !skip_layout {
408 if let Err(e) = self.resolve_layout(false) {
409 eprintln!(
410 "Warning: Layout resolution failed in get_evaluated_schema_by_paths: {}",
411 e
412 );
413 }
414 }
415
416 match format.unwrap_or(ReturnFormat::Nested) {
417 ReturnFormat::Nested => {
418 let mut result = Value::Object(serde_json::Map::new());
419 for path in paths {
420 if let Some(val) = self.get_schema_value_by_path(path) {
421 Self::insert_at_path(&mut result, path, val);
423 }
424 }
425 result
426 }
427 ReturnFormat::Flat => {
428 let mut result = serde_json::Map::new();
429 for path in paths {
430 if let Some(val) = self.get_schema_value_by_path(path) {
431 result.insert(path.clone(), val);
432 }
433 }
434 Value::Object(result)
435 }
436 ReturnFormat::Array => {
437 let mut result = Vec::new();
438 for path in paths {
439 if let Some(val) = self.get_schema_value_by_path(path) {
440 result.push(val);
441 } else {
442 result.push(Value::Null);
443 }
444 }
445 Value::Array(result)
446 }
447 }
448 }
449
450 pub fn get_schema_by_path(&self, path: &str) -> Option<Value> {
452 let pointer_path = path_utils::dot_notation_to_schema_pointer(path);
453 self.schema
454 .pointer(&pointer_path.trim_start_matches('#'))
455 .cloned()
456 }
457
458 pub fn get_schema_by_paths(&self, paths: &[String], format: Option<ReturnFormat>) -> Value {
460 match format.unwrap_or(ReturnFormat::Nested) {
461 ReturnFormat::Nested => {
462 let mut result = Value::Object(serde_json::Map::new());
463 for path in paths {
464 if let Some(val) = self.get_schema_by_path(path) {
465 Self::insert_at_path(&mut result, path, val);
466 }
467 }
468 result
469 }
470 ReturnFormat::Flat => {
471 let mut result = serde_json::Map::new();
472 for path in paths {
473 if let Some(val) = self.get_schema_by_path(path) {
474 result.insert(path.clone(), val);
475 }
476 }
477 Value::Object(result)
478 }
479 ReturnFormat::Array => {
480 let mut result = Vec::new();
481 for path in paths {
482 if let Some(val) = self.get_schema_by_path(path) {
483 result.push(val);
484 } else {
485 result.push(Value::Null);
486 }
487 }
488 Value::Array(result)
489 }
490 }
491 }
492
493 pub(crate) fn insert_at_path(root: &mut Value, path: &str, value: Value) {
495 let parts: Vec<&str> = path.split('.').collect();
496 let mut current = root;
497
498 for (i, part) in parts.iter().enumerate() {
499 if i == parts.len() - 1 {
500 if let Value::Object(map) = current {
502 map.insert(part.to_string(), value);
503 return; }
505 } else {
506 if !current.is_object() {
511 *current = Value::Object(serde_json::Map::new());
512 }
513
514 if let Value::Object(map) = current {
515 if !map.contains_key(*part) {
516 map.insert(part.to_string(), Value::Object(serde_json::Map::new()));
517 }
518 current = map.get_mut(*part).unwrap();
519 }
520 }
521 }
522 }
523
524 pub fn flatten_object(
526 prefix: &str,
527 value: &Value,
528 result: &mut serde_json::Map<String, Value>,
529 ) {
530 match value {
531 Value::Object(map) => {
532 for (k, v) in map {
533 let new_key = if prefix.is_empty() {
534 k.clone()
535 } else {
536 format!("{}.{}", prefix, k)
537 };
538 Self::flatten_object(&new_key, v, result);
539 }
540 }
541 _ => {
542 result.insert(prefix.to_string(), value.clone());
543 }
544 }
545 }
546
547 pub fn convert_to_format(value: Value, format: ReturnFormat) -> Value {
548 match format {
549 ReturnFormat::Nested => value,
550 ReturnFormat::Flat => {
551 let mut result = serde_json::Map::new();
552 Self::flatten_object("", &value, &mut result);
553 Value::Object(result)
554 }
555 ReturnFormat::Array => {
556 if let Value::Object(map) = value {
560 Value::Array(map.values().cloned().collect())
561 } else if let Value::Array(arr) = value {
562 Value::Array(arr)
563 } else {
564 Value::Array(vec![value])
565 }
566 }
567 }
568 }
569}