Skip to content

Commit 7263b03

Browse files
authored
Merge pull request #2583 from dathere/2579-tojsonl-number-format
fix: `tojsonl` display floats as per the JSON spec
2 parents b222573 + c710647 commit 7263b03

File tree

2 files changed

+46
-1
lines changed

2 files changed

+46
-1
lines changed

src/cmd/tojsonl.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ pub fn run(argv: &[&str]) -> CliResult<()> {
304304

305305
let mut header_key = Value::String(String::new());
306306
let mut temp_val = Value::String(String::new());
307+
let mut temp_numval: serde_json::Number;
307308

308309
if args.flag_trim {
309310
record.trim();
@@ -324,7 +325,19 @@ pub fn run(argv: &[&str]) -> CliResult<()> {
324325
}
325326
},
326327
JsonlType::Null => "null",
327-
JsonlType::Integer | JsonlType::Number => field,
328+
JsonlType::Integer => field,
329+
JsonlType::Number => {
330+
// round-trip thru serde_json to parse the number per the json spec
331+
// safety: we know the number is a valid f64 and the inner
332+
// unwrap_or(0.0) covers the bare
333+
// outer unwrap()
334+
temp_numval = serde_json::Number::from_f64(
335+
fast_float2::parse(field).unwrap_or(0.0),
336+
)
337+
.unwrap();
338+
temp_string2 = temp_numval.to_string();
339+
&temp_string2
340+
},
328341
JsonlType::Boolean => {
329342
if let 't' | 'y' | '1' = boolcheck(field, &mut temp_string2) {
330343
"true"

tests/test_tojsonl.rs

+32
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,38 @@ fn tojsonl_simple() {
2929
assert_eq!(got, expected);
3030
}
3131

32+
#[test]
33+
#[serial]
34+
fn tojsonl_2579() {
35+
let wrk = Workdir::new("tojsonl_2579");
36+
wrk.create(
37+
"in.csv",
38+
vec![
39+
svec!["Date", "Product", "Unit", "Price"],
40+
svec!["1937-01-01", "Milk", "1 gallon", ".1"],
41+
svec!["1937-01-01", "Bread", "1 loaf", ".09"],
42+
svec!["1937-01-01", "Movie ticket", "1 ticket", ".25"],
43+
svec!["1937-01-01", "Milk", "10 gallons", "1.00000"],
44+
svec!["1937-01-01", "Milk", "100 gallons", "10"],
45+
svec!["1937-01-01", "Taxi", "1 mile", "0.90000"],
46+
],
47+
);
48+
49+
let mut cmd = wrk.command("tojsonl");
50+
cmd.arg("in.csv");
51+
52+
wrk.assert_success(&mut cmd);
53+
54+
let got: String = wrk.stdout(&mut cmd);
55+
let expected = r#"{"Date":"1937-01-01","Product":"Milk","Unit":"1 gallon","Price":0.1}
56+
{"Date":"1937-01-01","Product":"Bread","Unit":"1 loaf","Price":0.09}
57+
{"Date":"1937-01-01","Product":"Movie ticket","Unit":"1 ticket","Price":0.25}
58+
{"Date":"1937-01-01","Product":"Milk","Unit":"10 gallons","Price":1.0}
59+
{"Date":"1937-01-01","Product":"Milk","Unit":"100 gallons","Price":10.0}
60+
{"Date":"1937-01-01","Product":"Taxi","Unit":"1 mile","Price":0.9}"#;
61+
assert_eq!(got, expected);
62+
}
63+
3264
#[test]
3365
#[serial]
3466
fn tojsonl_2294() {

0 commit comments

Comments
 (0)