18

I was wondering if it is possible to decode a JSON object in Rust that has an attribute name which is also a Rust keyword. I am working with the rustc-serialize crate and my struct definition looks like this:

#[derive(RustcDecodable)]
struct MyObj {
  type: String
}

The compiler throws an error because type is a keyword:

error: expected identifier, found keyword `type`
src/mysrc.rs:23     type: String,
                           ^~~~
BinaryButterfly
  • 18,137
  • 13
  • 50
  • 91
rking788
  • 431
  • 1
  • 5
  • 12
  • Is it safe to assume that the original data can't be changed to avoid the conflict? – Shepmaster Mar 17 '15 at 17:42
  • yes, it would be best if i didn't have to change the source data. I guess maybe creating a new struct field with a different name and writing a custom `impl Decodable` is the only way? – rking788 Mar 17 '15 at 18:34
  • I can see either manually implementing it or using `Json::from_str` and then poking into its result value. – Shepmaster Mar 17 '15 at 18:57

2 Answers2

27

You can use the serde crate. It supports renaming of fields since February 2015

Your example could then look like this:

#[derive(Deserialize)]
struct MyObj {
    #[serde(rename = "type")] 
    type_name: String
}
oli_obk
  • 28,729
  • 6
  • 82
  • 98
  • 1
    Seems like exactly what i was looking for. It says it does some lookahead, do you know if it is possible to parse an attribute that could be one of a few different types? so a field called msg could be either a JSON string or an array. – rking788 Mar 18 '15 at 15:02
  • That is one of the main reasons serde was invented, because the old deserializer couldn't read an enum without having read a tag beforehand. – oli_obk Mar 18 '15 at 15:48
1

This can be done without serde's field renaming by using raw identifiers. By adding r# in front of an identifier, a keyword name can be used.

Using rustc-serialize

#[derive(RustcDecodable)]
struct MyObj {
    r#type: String
}

Using serde

use serde::Deserialize;

#[derive(Deserialize)]
struct MyObj {
    r#type: String
}

Note that rustc-serialize is deprecated in favor of serde.

Anders Evensen
  • 579
  • 5
  • 15