2

I'm deserializing a struct from JSON:

fn main() {
  let raw_json = r#"{"error": {"msg": "I am an error message"}}"#;
  let error: Error = json::decode(raw_json).unwrap();

}

struct Error {
  message: &'static str
}

impl<D: Decoder<E>, E> Decodable<D, E> for Error {
  fn decode(d: &mut D) -> Result<Error, E> {
    d.read_struct("error", 1, |d| {
      Ok(Error{
        message: try!(d.read_struct_field("msg", 0u, |d| Decodable::decode(d)))
      })
    })
  }
}

But getting this error:

failed to find an implementation of trait serialize::serialize::Decodable<D,E> for &'static str

Adding lifetime to message does not help. Turns out there is no implementation of Decodable trait for &str, but only for String

How do I deserialize my JSON into &str struct field?

2 Answers 2

3

References can't be serialized or deserialized. A different approach is needed.

Your Error struct contains a &'static str. This means you could also represent errors in the form of an enum, which can be serialized. Then you could implement Show for Error.

extern crate serialize;
use serialize::{Decodable, Encodable};
use std::fmt;

#[deriving(Encodable, Decodable)]
enum Error {
    Foo,
    Bar
}

impl fmt::Show for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Foo => write!(f, "Foo happened"),
            Bar => write!(f, "Bar happened"),
        }
    }
}

The question is whether this is actually what you wanted. If you want the ability to represent an arbitrary error message (rather than a specific error type) then you'll have to use String.

extern crate serialize;
use serialize::{Decodable, Encodable};

#[deriving(Encodable, Decodable)]
struct Error {
    msg: String
}
Sign up to request clarification or add additional context in comments.

Comments

2

For &'static str, you must have a string literal, a string that lasts for lifetime of the entire process (a.k.a. forever). This evidently can’t be achieved.

For &'a str in general, something else must be owning the bytes—it is a reference to some of the contents of a String, in general (it might also be Vec<Ascii> or possibly another similar UTF-8 string type outside the standard library). This is not the way in which the serialization works—there is not necessarily a value stored anywhere permanent, so it can’t produce references. This is why it’s only implemented for String: you simply cannot have it for &str.

1 Comment

Thanks for this. My all problems stem from lack of understanding between str and String. Now finally I think I get it. String is the place where the actual string is stored, while &str is just a view on it. With literals, &str is just a view on a literal. So we can't deserialize the view, we can only do it for the real storage.

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.