Generate JSON file of all syn types

The JSON file can be used by third party libs to build tools that
consume `syn` types.
diff --git a/codegen/src/json.rs b/codegen/src/json.rs
new file mode 100644
index 0000000..e1b641d
--- /dev/null
+++ b/codegen/src/json.rs
@@ -0,0 +1,39 @@
+use crate::types;
+
+use std::fs::File;
+use std::io::prelude::*;
+use std::path::Path;
+
+pub fn generate(types: &[types::TypeDef]) {
+    let codegen_root = Path::new(env!("CARGO_MANIFEST_DIR"));
+
+    let mut f = File::open(codegen_root.join("../Cargo.toml")).unwrap();
+    let mut s = String::new();
+    f.read_to_string(&mut s).unwrap();
+
+    let manifest: Manifest = toml::from_str(&s).unwrap();
+
+    let f = ::std::fs::File::create(codegen_root.join("../syn.json")).unwrap();
+
+    serde_json::to_writer_pretty(f, &Introspect {
+        version: &manifest.package.version,
+        types,
+    }).unwrap();
+}
+
+#[derive(Debug, Deserialize)]
+struct Manifest {
+    package: Package,
+}
+
+#[derive(Debug, Deserialize)]
+struct Package {
+    version: String,
+}
+
+#[derive(Debug, Serialize)]
+struct Introspect<'a> {
+    /// The `syn` version used to generate the introspection file
+    version: &'a str,
+    types: &'a [types::TypeDef],
+}
diff --git a/codegen/src/main.rs b/codegen/src/main.rs
index fa577cb..1860211 100644
--- a/codegen/src/main.rs
+++ b/codegen/src/main.rs
@@ -20,12 +20,19 @@
 extern crate rustfmt_nightly as rustfmt;
 #[macro_use]
 extern crate syn;
+extern crate serde;
+#[macro_use]
+extern crate serde_derive;
+extern crate serde_json;
+extern crate toml;
 
 mod gen;
+mod json;
 mod parse;
 mod types;
 
 fn main() {
     let types = parse::parse();
     gen::generate(&types);
+    json::generate(&types);
 }
diff --git a/codegen/src/types.rs b/codegen/src/types.rs
index 76c3773..3770f41 100644
--- a/codegen/src/types.rs
+++ b/codegen/src/types.rs
@@ -1,12 +1,13 @@
 use std::ops;
 
-#[derive(Debug)]
+#[derive(Debug, Serialize)]
+#[serde(rename_all = "snake_case")]
 pub enum TypeDef {
     Struct(Struct),
     Enum(Enum),
 }
 
-#[derive(Debug)]
+#[derive(Debug, Serialize)]
 pub struct Struct {
     ident: String,
     features: Features,
@@ -14,26 +15,27 @@
     all_fields_pub: bool,
 }
 
-#[derive(Debug)]
+#[derive(Debug, Serialize)]
 pub struct Enum {
     ident: String,
     features: Features,
     variants: Vec<Variant>,
 }
 
-#[derive(Debug)]
+#[derive(Debug, Serialize)]
 pub struct Variant {
     ident: String,
     fields: Vec<Type>,
 }
 
-#[derive(Debug)]
+#[derive(Debug, Serialize)]
 pub struct Field {
     ident: String,
     ty: Type,
 }
 
-#[derive(Debug)]
+#[derive(Debug, Serialize)]
+#[serde(rename_all = "snake_case")]
 pub enum Type {
     /// Type defined by `syn`
     Item(String),
@@ -58,13 +60,13 @@
     Tuple(Vec<Type>),
 }
 
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Serialize)]
 pub struct Token {
     repr: String,
     ty: String,
 }
 
-#[derive(Debug, Default, Clone)]
+#[derive(Debug, Default, Clone, Serialize)]
 pub struct Features {
     any: Vec<String>,
 }
@@ -168,10 +170,6 @@
     pub fn repr(&self) -> &str {
         &self.repr
     }
-
-    pub fn ty(&self) -> &str {
-        &self.ty
-    }
 }
 
 impl Features {