Change:
Currently, the Json Decoder fails if the JSON it is decoding lacks a field in the Decodable struct it is mapping onto. I propose that if a struct field maps to an Option, the Json Decoder would handle missing fields by mapping None to the field. Here's a code example: This fails at runtime with the error message: I discussed this in the #rust IRC channel and cmr said this sounded reasonable when optional fields map to fields and suggested I file it here as a enhancement request.
Hi Did you come up with any good workaround for this issue?
The workaround was to have the "null" field be empty string instead. Not very satisfactory. I ended up not needing the Option<field in my struct so haven't worked on this issue. I just tried the latest version of rustc to see how it works now, but got caught in a endless cycle of compiler errors that I didn't have enough motivation to wade through.
So you were also in control of the JSON format that you were trying to decode? I unluckily am not, so I need to find some other way.
If this is approved as an enhancement I'd be interested in tackling this.
I'm currently working on a fix for this. I have a simple one that only works for Json, but I'm working on updating the Deccodable expansion to provide an optional field, so it will work with any type where an optional value will work. I'm stuck on figuring out what type an object is during deriving(Decodable) expansion, however.
So, the problem comes from Decoder not knowing that a value is optional until the field name is read: A special case would likely need to be in the deriving code to check if the value should be an option, and not Err if not found. Currently, you can get around this by just not , since you can't use the default impl. For the LogEntry example, it could look like this:
Not sure if you're already aware, but an alternative to using the empty string to represent an "empty" string field would be use a null value for that key in the JSON, which will deserialize to None: deserializes to . The problem you reported is still there for missing keys though. Given that null can be used to deserialize a field as None, would it be reasonable to provide two Decoder structs in serialize::json: one which defaults any missing Option<Tfields as None, and a stricter one which has the current behavior of erroring when any field is missing?
it'd be quite difficult to do that. As I said, the call to happens before , so the isn't able to know that the struct field should be optional.
Didn't see your comment while I was writing mine, makes sense.
The quick way I had set it up for json only was to try readoption if readstructfield failed, and if readoption failed, to only then throw the missing field error.
Sorry, I mistyped, it puts a null on the stack, then tries read_option, so that if it was an optional field, it will read null/None, then if that fails it wasn't an optional field.
Anybody working on this??
+1 for to represent fields that may not be present; I would like to see this implemented. Concerns for symmetry though: Let's say that you have a field whose type is , and the object, prior to serialisation, contains for that value, what should the serialised output look like: Should it contain that key with a value of , or should that key not be present? Should we have a mechanism for being able to specify default values?
How about passing an object with defaults and passing it to decode?
That sounds good, although I would still prefer being able to specify the defaults when declaring the struct.
I'm working on this as part of my serialization rewrite
I've looked through a few issues now and I'm struggling to find where this has previously been mentioned: Is it possible to require the trait for all types that implement to solve the missing fields issue? I'm sure there are reasons something like this has been avoided, I just haven't run across them yet and I'd love to hear them! My recent use case is within my audio synthesis instrument library - development currently involves lots of back and forth between testing and adding/removing fields. Each time I add or remove fields within the data structure my library loading starts to fail and I have to either discard the library and start designing the instruments again from scratch or manually add/remove fields to/from the .json file. If I were able to specify default values instead of having the loading fail, it would make the whole process much smoother. I understand that this may not be an issue for other users of - Perhaps it would be better to have a separate trait (i.e. ) that uses defaults in the method where would normally fail?
I did not see your comment before writing my PR for this issue. RFC seems useful. I do think some manner of defaults for fields should be there, but I'm not certain how best to approach it. It would require a slightly larger rewrite of whatever way we want to do it. Maybe add these comments to rust-lang/rfcs?

Discussion:
let mut obj = try!(expect!(self.pop(), Object)); let value = match obj.pop(&name.to_string()) { <del> None => return Err(MissingFieldError(name.to_string())), </del> <ins> None => { // Add a Null and try to parse it as an Option<_> // to get None as a default value. self.stack.push(Null); match f(self) { Ok(x) => x, Err(_) => return Err(MissingFieldError(name.to_string())), } }, </ins> Some(json) => { self.stack.push(json); try!(f(self))

} fn read_option<T>(&mut self, f: |&mut Decoder, bool| -> DecodeResult<T>) -> DecodeResult<T> { <ins> debug!("read_option()"); </ins> match self.pop() { Null => f(self, false), value => { self.stack.push(value); f(self, true) }

use std::{i64, u64, f32, f64, io}; use std::collections::TreeMap; <ins> #[deriving(Decodable, Eq, PartialEq, Show)] struct OptionData { opt: Option<uint>, } #[test] fn test_decode_option_none() { let s ="{}"; let obj: OptionData = super::decode(s).unwrap(); assert_eq!(obj, OptionData { opt: None }); } #[test] fn test_decode_option_some() { let s = "{ "opt": 10 }"; let obj: OptionData = super::decode(s).unwrap(); assert_eq!(obj, OptionData { opt: Some(10u) }); } #[test] fn test_decode_option_malformed() { check_err::<OptionData>("{ "opt": [] }", ExpectedError("Number".to_string(), "[]".to_string())); check_err::<OptionData>("{ "opt": false }", ExpectedError("Number".to_string(), "false".to_string())); } </ins> #[deriving(PartialEq, Encodable, Decodable, Show)] enum Animal { Dog,