0

I'm trying to get a deeply-nested JSON object from a vector of strings using the json crate:

fn main() {   
    let my_vec = ["foo", "bar", "baz", "foobar", "barfoo"];
    let mut curr_obj = object!();
    for i in 0..my_vec.len() {
        let name = my_vec[i];
        curr_obj = addObj(curr_obj, name);   
    }
}

fn addObj(mut obj: json::JsonValue, name: &str) -> json::JsonValue {
    obj[name] = json::JsonValue::new_object();
    let retob = obj[name];
    retob.to_owned() // is empty but should be obj["foo"] = object!();
}

The object is an empty one here. My desired output looks like this:

{
  "foo": {
    "bar": {
      "baz": {
        "foobar": {
          "barfoo": {}
        }
      }
    }
  }
}

I get the error

error[E0507]: cannot move out of indexed content
  --> src/main.rs:15:17
   |
15 |     let retob = obj[name];
   |                 ^^^^^^^^^
   |                 |
   |                 cannot move out of indexed content
   |                 help: consider using a reference instead: `&obj[name]`
1
  • addObj is not idiomatic Rust style, it should be snake_case: add_obj. Commented Oct 14, 2017 at 14:09

2 Answers 2

3

It can be done with a little bit of magic.

fn main() {   
    let my_vec = ["foo","bar","baz","foobar","barfoo"];
    let mut curr_obj = object!();
    {
        let mut obj_ref = &mut curr_obj;
        for i in 0..my_vec.len() {
            let name = my_vec[i];
            obj_ref = &mut {obj_ref}[name]; // note the curly braces
        }
    }
    println!("{:?}", curr_obj);
}

Mutable reference is moved instead of being reborrowed.

Sign up to request clarification or add additional context in comments.

4 Comments

I remember there was similar question, but I can't find it right now.
Can you please add more details (or a reference) about the magic of curly braces and the distinction between moving and reborrowing the mutable reference?
I need to go. Search SO for reborrowing, there is good description.
you sir - are a genius :)
1

It's much simpler to use iterator methods:

#[macro_use]
extern crate json;

fn main() {
    let my_vec = ["foo", "bar", "baz", "foobar", "barfoo"];

    let result = my_vec.iter().rev().fold(object!(), |object, name| {
        object!(name => object)
    });

    println!("{}", json::stringify_pretty(result, 2));
}

Produces:

{
  "foo": {
    "bar": {
      "baz": {
        "foobar": {
          "barfoo": {}
        }
      }
    }
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.