es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cuál es la forma en Rust de llamar a un método que requiere una porción de cadena desde un `String`?

Soy un principiante en Rust (pero un programador experimentado) y estoy tratando de crear una función de utilidad simple para leer datos de un archivo JSON, pero claramente me falta una comprensión importante de Rust para lograrlo. He buscado, pero no pude hacer que funcionara con las otras preguntas de Rust. Estoy tratando de hacer algo como esto:

pub fn leer_datos_desde_json<'a, T: Deserialize<'a>, P: AsRef<path>>(ruta: P) -> T {
    let resultado = std::fs::read_to_string(ruta).unwrap();
    return serde_json::from_str(&resultado).unwrap();
}

El problema es que quiero proporcionar a serde_json::from_str() el &str que requiere, pero obtengo un String al leer el archivo. Entonces, el compilador de Rust dice:

40 |     return serde_json::from_str(&result).unwrap();
   |            ---------------------^^^^^^^-
   |            |                    |
   |            |                    el valor prestado no vive lo suficiente

La causa es obviamente que la variable resultado se libera antes de que from_str() termine con el valor, pero no pude obtener “solo la porción” con el valor. He intentado con as_str(), &*, &'static str y varias otras opciones para intentar hacer que esto funcione, pero claramente me falta algo, ya que parece un caso de uso básico. Debo admitir que todavía estoy un poco confundido con “lifetime” y los genéricos involucrados, por lo que el problema podría estar allí.

Tags:  ,

Answer

  1. Avatar for davy.ai

    Solución

    El problema aquí es que la variable result es de tipo String, y serde_json::from_str() espera un &str. La referencia &String creada por &result solo durará hasta el final del ámbito de la función, por lo que no es una solución válida.

    Una forma de solucionar esto es usar el método as_str() del tipo String para obtener una referencia &str a los datos subyacentes. Esto creará una referencia que durará tanto como la propia String.

    Así es como se vería la función modificada:

    use std::path::Path;
    use serde::Deserialize;
    
    pub fn read_data_from_json<'a, T: Deserialize<'a>, P: AsRef<path>>(path: P) -> T {
        let result = std::fs::read_to_string(path).unwrap();
        return serde_json::from_str(result.as_str()).unwrap();
    }
    

    Observa que no hay cambios en las restricciones genéricas ni en la firma de la función.

    La llamada result.as_str() devuelve una referencia &str a los datos dentro de la String. Esta referencia es válida mientras la String misma, por lo que podemos pasarla de forma segura a serde_json::from_str().

    Con esta modificación, la función debería funcionar correctamente y devolver los datos deserializados del archivo JSON.

Comments are closed.