Borrow solution for this case


#1

Hello,

I have the following borrow problem when trying to truncate a json::Array to 2 in length using cargo:json
I have a “fix” but I wondered what would be the ideal solution here. I have commented the borrow problems. There may also be another way to truncate the array, however I’d like to get the chosen method working first.

let first_two = op["operationStatuses"].members().take(2).cloned(); // Immutable borrow on "op"
let new_statuses = first_two.collect::<Vec<json::JsonValue>>();
op["operationStatuses"] = new_statuses.into(); // Mutable borrow on "op"

“Fix”:
let os = op[“operationStatuses”].clone(); // Clone must be separate let statement
let first_two = os.members().take(2).cloned();
let new_statuses = first_two.collect::<Vecjson::JsonValue>();
op[“operationStatuses”] = new_statuses.into();

Other methods I’ve thought of could include Slicing a clone instead, or a filter predicate, which I will investigate shortly.


#2

You may find it easier to implement this using a strongly typed data structure rather than something like JsonValue. Once you have a struct where operationStatuses is just a Vec, it only requires calling Vec::truncate to truncate the length. The code is more readable and you get better error messages if the JSON input does not match the shape that your program assumes.

#[macro_use]
extern crate serde_derive;
extern crate serde_json;

use serde_json::Value;

#[derive(Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
struct Murk {
    operation_statuses: Vec<Value>,
}

fn main() {
    let j = "{\"operationStatuses\":[1, 2, 3, 4, 5, 6]}";
    let mut op: Murk = serde_json::from_str(j).unwrap();

    // Truncate Vec to at most two elements.
    op.operation_statuses.truncate(2);

    println!("{:?}", op);
}