I should note that this is my second day of Rust and I got thru the first day via shear bloody mindedness. I finally came up with the working, albeit ugly, match statement that is the core of a module that parses semi-structured json blobs.
I should also mention that this is a port from Python to Rust... That's how I learn. Anyway...
I have a match statement which is a really just a bunch of if
statements in disguise:
fn flatten_tasks(task: &Value, task_id: String) {
let task_id = get_task_id(task, task_id);
match task {
Value::Object(obj)
if obj.contains_key("value")
&& obj["value"].is_array()
&& obj["value"][0].is_string() =>
{
add_list_of_values(task, task_id);
}
Value::Object(obj) if obj.contains_key("value") && obj["value"].is_array() => {
nested_tasks(task, task_id);
}
Value::Object(obj) if obj.contains_key("tool_label") && obj.contains_key("width") => {
add_box_values(task, task_id);
}
Value::Object(obj) if obj.contains_key("tool_label") && obj.contains_key("x1") => {
add_length_values(task, task_id);
}
Value::Object(obj) if obj.contains_key("tool_label") && obj.contains_key("x") => {
add_point_values(task, task_id);
}
Value::Object(obj) if obj.contains_key("tool_label") && obj.contains_key("details") => {
add_values_from_workflow(task, task_id);
}
Value::Object(obj) if obj.contains_key("select_label") => add_selected_value(task, task_id),
Value::Object(obj) if obj.contains_key("task_label") => add_text_value(task, task_id),
_ => panic!("Unkown field type in: {:?}", task),
}
}
It looks much cleaner in python due to the lack of if
arms. Is it possible to to something similar in Rust?
def flatten_annotation(anno, row, workflow_strings, task_id=""):
"""Flatten one annotation recursively."""
task_id = anno.get("task", task_id)
match anno:
case {"value": [str(), *__], **___}:
list_annotation(anno, row, task_id)
case {"value": list(), **__}:
subtask_annotation(anno, row, workflow_strings, task_id)
case {"select_label": _, **__}:
select_label_annotation(anno, row, task_id)
case {"task_label": _, **__}:
task_label_annotation(anno, row, task_id)
case {"tool_label": _, "width": __, **___}:
box_annotation(anno, row, task_id)
case {"tool_label": _, "x1": __, **___}:
length_annotation(anno, row, task_id)
case {"tool_label": _, "x": __, **___}:
point_annotation(anno, row, task_id)
case {"tool_label": _, "details": __, **___}:
workflow_annotation(anno, row, workflow_strings, task_id)
case _:
print(f"Annotation type not found: {anno}")
Edit: Sorry for the crappy question: (I'll add more as I uncrapify this)
- This is serde_json
- I only know what some of the data is, as in there are extra-fields that I don't control.
- The structure of the json is only known at the leaves.