Skip to content

Instantly share code, notes, and snippets.

@oconnor663
Created April 3, 2019 22:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oconnor663/8844b2e28ff91006f4cd5cd90b42ad99 to your computer and use it in GitHub Desktop.
Save oconnor663/8844b2e28ff91006f4cd5cd90b42ad99 to your computer and use it in GitHub Desktop.
dirty JSON with nom
use nom::types::CompleteStr;
use nom::*;
use std::collections::HashMap;
#[derive(Clone, Debug)]
enum Value {
Num(f64),
String(String),
List(Vec<Value>),
Object(HashMap<String, Value>),
}
named!(
json_string(CompleteStr) -> String,
map!(
delimited!(char!('"'), is_not!("\""), char!('"')),
|s| s.to_string()
)
);
named!(
json_list(CompleteStr) -> Vec<Value>,
delimited!(
char!('['),
separated_list!(tag!(","), json_value),
char!(']')
)
);
named!(
json_object_pair(CompleteStr) -> (String, Value),
separated_pair!(json_string, tag!(":"), json_value)
);
named!(
json_object(CompleteStr) -> Vec<(String, Value)>,
// Note that for some reason the ws! in json_value doesn't propagate here.
ws!(delimited!(
char!('{'),
separated_list!(
tag!(","),
separated_pair!(json_string, tag!(":"), json_value)
),
char!('}')
))
);
named!(
json_value(CompleteStr) -> Value,
// Note that ws! here inserts whitespace allowances throughout.
ws!(alt!(
double => { |n| Value::Num(n) } |
json_string => { |s| Value::String(s) } |
json_list => { |v| Value::List(v) } |
json_object => { |v: Vec<(String, Value)>| {
Value::Object(v.into_iter().collect::<HashMap<_,_>>())
}}
))
);
fn parse(s: &str) -> Value {
let (_, v) = json_value(CompleteStr(s)).unwrap();
v
}
fn main() {
let cases = [
"\"this is a nice long string with a float 3.14159\"",
"1.45",
"\" foo \"",
"[0 , 1.5 , \"bar\"]",
"{\"foo\": 5 , \"bar\":[\"baz\" , 5]}",
];
for case in &cases {
println!("{}\n{:?}\n", case, parse(case));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment