Fix serde lifetime issue when using lazy_static

Fix serde lifetime issue when using lazy_static

I'd like to read some json into a static HashMap, and am using lazy_static and serde, but I can't figure out how (if at all) I can fix this serde lifetime issue:

#[macro_use]
extern crate lazy_static;
use std::fs::File;
use std::io::BufReader;
use std::collections::HashMap;

lazy_static! {
    static ref KEYWORDS: HashMap<&'static str, i32> = {
        let file = File::open("words.json").unwrap();
        let reader = BufReader::new(file);
        serde_json::from_reader(reader).unwrap()
    };
}

playground link

error: implementation of serde::de::Deserialize is not general enough note: HashMap<&str, i32> must implement serde::de::Deserialize<'0>, for any lifetime '0 note: but HashMap<&str, i32> actually implements serde::de::Deserialize<'1>, for some specific lifetime '1

words.json is a simple json map: {"aaargh": 1}.

I'm open to another, non-lazy_static approach if need be.


The error message is telling you that you can't deserialize to a &'static str. As the deserializer goes along creating the entries, the &str keys could only have as long a lifetime as a borrow of the buffer the deserializer is reading the file into. But &'static str must point to a str which lives forever.

I see two solutions here: The easy way and the hard way.

The easy way: Just change &'static str in the type to String and it compiles. This way the HashMap owns the keys; serde already knows how to deserialize owned strings.

static ref KEYWORDS: HashMap<String, i32> = { // ...

The hard way: Technically you can still get your HashMap<&'static str, i32> by leaking the backing buffers of the Strings. Normally "leaking" is bad, but since this is a lazy static, it really makes no difference as those buffers would never be freed anyways. Getting a &'static str by leaking a String looks like this:

fn leak_string(from: String) -> &'static str {
    Box::leak(from.into_boxed_str())
}

The problem is that serde doesn't do this automatically. One way to accomplish this would be to deserialize to the HashMap<String, i32> first and then convert it to HashMap<&'static string, i32> by taking each of the entries and inserting them into a new HashMap after running the keys through leak_string. This is inefficient as there was no need to collect into a HashMap in the first place. A better solution would involve writing a custom deserializer that did leak_string "on the fly". Since the easy way is so much easier, and there's some stumbling blocks for this hard way, I don't think it's useful to provide a full code sample here.

The only real advantage of "the hard way" vs "the easy way" is that "the hard way" requires one pointer's worth less memory for each key in the HashMap (&str is pointer+len; String is pointer+len+capacity). It's also nice in that it doesn't change your type signature, but there's very little you can do with a &'static str that you can't do with a String.

Highest Voted 'serde' Questions - Page 4, Serde is a framework for serializing and deserializing Rust data structures efficiently and generically. 2. 1 Fix serde lifetime issue when using lazy_static. To explain where the lifetime errors are coming from: because RelObject needs to borrow &'a str, it can only deserialize from data that outlives 'a. Serde will implicitly borrow fields of type &str without you having to ask for it. But RelData does not ask to borrow anything so it expects to be able to deserialize from data that has any lifetime.


When using serde_json::from_str to deserialize from &strHashMap<&str, i32>, the input JSON string needs to outlive the string slices in the output. This is the role of the 'a lifetime in the signature: https://docs.rs/serde_json/1.0.40/serde_json/fn.from_str.html

That means if the output needs to contain string slices with 'static lifetime, the input JSON data must also have 'static lifetime. We know how to do that -- lazy_static!

use lazy_static::lazy_static;
use std::collections::HashMap;

lazy_static! {
    static ref KEYWORDS: HashMap<&'static str, i32> = {
        lazy_static! {
            static ref WORDS_JSON: String = {
                std::fs::read_to_string("words.json").unwrap()
            };
        }
        serde_json::from_str(&WORDS_JSON).unwrap()
    };
}

Seriously stupid lifetime problem - help, 39 | fn validate<'de, E>(filename: &str, dto: E) | --- lifetime `'de` defined here . I'd like to understand it (as well as the correct fix) a bit better if anyone can offer some insight. The issue with your code is as follows use lazy_static::​lazy_static; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use  I have been using serde to deserialize json and it has been very easy to use and helpful. However, I have a question regarding deserializing to a struct with a lifetime. Take the following for example: #[derive(Deserialize)] struct Perso


The culprit here is how serde_json::from_reader is defined. From its documentation:

pub fn from_reader<R, T>(rdr: R) -> Result<T> where
    R: Read,
    T: DeserializeOwned,

So, the result must be owned data, not borrowed. Even the &'static won't do. You have to use String here:

lazy_static! {
    static ref KEYWORDS: HashMap<String, i32> = {
        let file = File::open("words.json").unwrap();
        let reader = BufReader::new(file);
        serde_json::from_reader(reader).unwrap()
    };
}

Cannot infer an appropriate lifetime when sharing self reference , However, this causes a lifetime conflict: error[E0495]: cannot infer an thus evading the issue of having a deserialized object with different lifetime boundaries. How can we build a generic function that, using Serde, serializes an object Can [placing a ReadHandle / WriteHandle directly in a lazy static variable] be done? Of course, for the most normal case I think we don’t need this one, and if at future '_ lifetime introduced the problem could be resolved(but I’m not sure that is for this problem actually so just a guess). Thanks for reading and see you next time.


Lifetime errors with skipped `&'static` variable · Issue #1078 · serde , I needed to evolve my format, so I went from (simplified) #[derive(Debug, PartialEq)] #[derive(Serialize, Deserialize)]  Lifetime issue Hi I am learning Rust by trying to make a simple application that will browse all my digital music collection and generate a json file that in the future I wll try to store in a embed DB (instead of have a handmade Excel file).


rust static lifetime - Search, rust - Fix serde lifetime issue when using lazy_static stackoverflow.com. Stack Overflow Public questions and answers; That means if the output needs to. @TrionProg you're running into a problem here where the versions are not matching up, and to get things to work you'll need them to match up. One of your dependencies is postgres, which currently uses uuid 0.4. You'll need to use uuid 0.4 in that case. The uuid 0.4 crate depends on serde 0.9, so you'll need to use serde 0.9 in that case.


Rust - Globals, Sometimes using global static mutable variables in multi-threaded code can be Use the lazy_static crate to create global immutable variables which are  HIVE-16922 fixed the typo of org.apache.hadoop.hive.serde.serdeConstants#COLLECTION_DELIM, but also introduced a breaking change. #1321 fixed this compatibility issue for RC files, while leaving TEXT files out.