fuzzy-from-json-value 0.1.0

todo: write a description here
Documentation
// ---------------- [ File: fuzzy-from-json-value/src/flatten_fields_if_present.rs ]
crate::ix!();

#[tracing::instrument(level = "trace", skip_all)]
pub fn flatten_fields_if_present(obj: &mut serde_json::Map<String, serde_json::Value>) {
    // If the JSON object contains a "fields" key and it's an object,
    // we move all keys from that sub-object up into the parent object.
    if let Some(fields_val) = obj.remove("fields") {
        if let serde_json::Value::Object(fields_map) = fields_val {
            trace!("Detected 'fields' object => flattening into top-level.");
            for (k, v) in fields_map {
                // If there's a collision, we'll just log and skip
                if obj.contains_key(&k) {
                    warn!("While flattening 'fields', key '{}' already exists in top-level => skipping overwrite.", k);
                    continue;
                }
                obj.insert(k, v);
            }
        } else {
            debug!("Key 'fields' is present but not an object => putting it back into top-level as 'fields'.");
            obj.insert("fields".to_string(), fields_val);
        }
    } else {
        trace!("No 'fields' key found => nothing to flatten.");
    }
}

/// If `value` is an Object containing a key "fields" which is itself an Object,
/// lift those "fields" up one level. Then remove the "fields" key.
///
/// Recurse into children as well for arrays or objects.
pub fn flatten_fields_if_present_in_value(value: &mut serde_json::Value) {
    match value {
        serde_json::Value::Object(obj) => {
            if let Some(fields_val) = obj.remove("fields") {
                // If it's an object, merge it in.
                if let serde_json::Value::Object(fields_map) = fields_val {
                    for (k, v) in fields_map {
                        obj.insert(k, v);
                    }
                } else {
                    // else put it back
                    obj.insert("fields".to_string(), fields_val);
                }
            }
            // Recurse into each child
            for (_k, child) in obj.iter_mut() {
                flatten_fields_if_present_in_value(child);
            }
        }
        serde_json::Value::Array(arr) => {
            // Recurse into each element
            for elem in arr {
                flatten_fields_if_present_in_value(elem);
            }
        }
        _ => {
            // do nothing for scalars
        }
    }
}