I can not deserialize json String to struct with serde

Viewed 1016

I have trouble deserializing json to struct.

Here is code that simulates my problem:

use std::sync::mpsc;
use std::sync::mpsc::{Receiver, Sender };

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

#[derive(Deserialize, Debug)]
struct Foo<'a> {
    a: u32,
    b: u32,
    c: &'a str,
}

fn main() {

    let (msg_tx, msg_rx): (Sender<Foo>, Receiver<Foo>) = mpsc::channel();
    {
        let js = r#"{"a":33, "b":44, "c": "ss"}"#; // initially I have a json String, here I simulate a problem
        let js_string = String::from(js);
        let f = test(js_string.as_str());

        msg_tx.send(f);
    }
}

fn test(js: &str) -> Foo {
    let foo: Foo = serde_json::from_str(js).unwrap();

    foo
}

Running that code results to the error 'js' does not live long enough. I know that changing the type of Foo c field to String will resolve the problem, but I would like to know if there is a another solution. The reason for this error is the way serde crate works in that situation, - it uses inside returned foo variable a reference to original variable, which is js_string, so it goes out of scope just after calling msg_tx.send(f); but f has a reference to it and lives longer than that scope. I'm still a rust beginner and want to master lifetime concept. I tried to fix my problem with function wrapper to set right lifetime, but failed.

1 Answers

You have to ensure that js_string lives longer than the channel, to ensure this you can create a scope for "working" with the channel:

use std::sync::mpsc;
use std::sync::mpsc::{Receiver, Sender };

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

#[derive(Deserialize, Debug)]
struct Foo<'a> {
    a: u32,
    b: u32,
    c: &'a str,
}

fn main() {

    let js = r#"{"a":33, "b":44, "c": "ss"}"#;
    let js_string = String::from(js);
    let f = test(js_string.as_str());
    {
        let (msg_tx, msg_rx): (Sender<Foo>, Receiver<Foo>) = mpsc::channel();
        msg_tx.send(f);
        
    } // channel is dropped here and js_string is no longer borrowed


} // js_string is dropped here

fn test(js: &str) -> Foo {
    let foo: Foo = serde_json::from_str(js).unwrap();
    foo
}
Related