Skip to content

Commit 2265512

Browse files
olsonjefferyalexcrichton
authored andcommitted
closes #12967 fix [en|de]coding of HashMap<K,V> where K is a numeric type
serialize: ref #12697 minor adj. to last char check + prettyencode test
1 parent 20e178c commit 2265512

File tree

1 file changed

+84
-1
lines changed

1 file changed

+84
-1
lines changed

src/libserialize/json.rs

+84-1
Original file line numberDiff line numberDiff line change
@@ -464,8 +464,20 @@ impl<'a> ::Encoder for Encoder<'a> {
464464
}
465465

466466
fn emit_map_elt_key(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
467+
use std::str::from_utf8;
467468
if idx != 0 { try!(write!(self.wr, ",")) }
468-
f(self)
469+
// ref #12967, make sure to wrap a key in double quotes,
470+
// in the event that its of a type that omits them (eg numbers)
471+
let mut buf = MemWriter::new();
472+
let mut check_encoder = Encoder::new(&mut buf);
473+
f(&mut check_encoder);
474+
let buf = buf.unwrap();
475+
let out = from_utf8(buf).unwrap();
476+
let needs_wrapping = out.char_at(0) != '"' &&
477+
out.char_at_reverse(out.len()) != '"';
478+
if needs_wrapping { try!(write!(self.wr, "\"")); }
479+
f(self);
480+
if needs_wrapping { try!(write!(self.wr, "\"")); }
469481
}
470482

471483
fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut Encoder<'a>|) {
@@ -659,13 +671,25 @@ impl<'a> ::Encoder for PrettyEncoder<'a> {
659671
}
660672

661673
fn emit_map_elt_key(&mut self, idx: uint, f: |&mut PrettyEncoder<'a>|) {
674+
use std::str::from_utf8;
662675
if idx == 0 {
663676
try!(write!(self.wr, "\n"));
664677
} else {
665678
try!(write!(self.wr, ",\n"));
666679
}
667680
try!(write!(self.wr, "{}", spaces(self.indent)));
681+
// ref #12967, make sure to wrap a key in double quotes,
682+
// in the event that its of a type that omits them (eg numbers)
683+
let mut buf = MemWriter::new();
684+
let mut check_encoder = PrettyEncoder::new(&mut buf);
685+
f(&mut check_encoder);
686+
let buf = buf.unwrap();
687+
let out = from_utf8(buf).unwrap();
688+
let needs_wrapping = out.char_at(0) != '"' &&
689+
out.char_at_reverse(out.len()) != '"';
690+
if needs_wrapping { try!(write!(self.wr, "\"")); }
668691
f(self);
692+
if needs_wrapping { try!(write!(self.wr, "\"")); }
669693
}
670694

671695
fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut PrettyEncoder<'a>|) {
@@ -1306,9 +1330,15 @@ impl ::Decoder for Decoder {
13061330
}
13071331

13081332
fn read_f64(&mut self) -> f64 {
1333+
use std::from_str::FromStr;
13091334
debug!("read_f64");
13101335
match self.stack.pop().unwrap() {
13111336
Number(f) => f,
1337+
String(s) => {
1338+
// re: #12967.. a type w/ numeric keys (ie HashMap<uint, V> etc)
1339+
// is going to have a string here, as per JSON spec..
1340+
FromStr::from_str(s).unwrap()
1341+
},
13121342
value => self.expected("number", &value)
13131343
}
13141344
}
@@ -2519,4 +2549,57 @@ mod tests {
25192549
let expected_null = ();
25202550
assert!(json_null.is_some() && json_null.unwrap() == expected_null);
25212551
}
2552+
2553+
#[test]
2554+
fn test_encode_hashmap_with_numeric_key() {
2555+
use std::str::from_utf8;
2556+
use std::io::Writer;
2557+
use std::io::MemWriter;
2558+
use collections::HashMap;
2559+
let mut hm: HashMap<uint, bool> = HashMap::new();
2560+
hm.insert(1, true);
2561+
let mut mem_buf = MemWriter::new();
2562+
{
2563+
let mut encoder = Encoder::new(&mut mem_buf as &mut io::Writer);
2564+
hm.encode(&mut encoder)
2565+
}
2566+
let bytes = mem_buf.unwrap();
2567+
let json_str = from_utf8(bytes).unwrap();
2568+
match from_str(json_str) {
2569+
Err(_) => fail!("Unable to parse json_str: {:?}", json_str),
2570+
_ => {} // it parsed and we are good to go
2571+
}
2572+
}
2573+
#[test]
2574+
fn test_prettyencode_hashmap_with_numeric_key() {
2575+
use std::str::from_utf8;
2576+
use std::io::Writer;
2577+
use std::io::MemWriter;
2578+
use collections::HashMap;
2579+
let mut hm: HashMap<uint, bool> = HashMap::new();
2580+
hm.insert(1, true);
2581+
let mut mem_buf = MemWriter::new();
2582+
{
2583+
let mut encoder = PrettyEncoder::new(&mut mem_buf as &mut io::Writer);
2584+
hm.encode(&mut encoder)
2585+
}
2586+
let bytes = mem_buf.unwrap();
2587+
let json_str = from_utf8(bytes).unwrap();
2588+
match from_str(json_str) {
2589+
Err(_) => fail!("Unable to parse json_str: {:?}", json_str),
2590+
_ => {} // it parsed and we are good to go
2591+
}
2592+
}
2593+
#[test]
2594+
fn test_hashmap_with_numeric_key_can_handle_double_quote_delimited_key() {
2595+
use collections::HashMap;
2596+
use Decodable;
2597+
let json_str = "{\"1\":true}";
2598+
let json_obj = match from_str(json_str) {
2599+
Err(_) => fail!("Unable to parse json_str: {:?}", json_str),
2600+
Ok(o) => o
2601+
};
2602+
let mut decoder = Decoder::new(json_obj);
2603+
let hm: HashMap<uint, bool> = Decodable::decode(&mut decoder);
2604+
}
25222605
}

0 commit comments

Comments
 (0)