first cut at JSON deparser
Matt S Trout [Tue, 19 Jun 2012 16:29:08 +0000 (16:29 +0000)]
json.tcl [new file with mode: 0644]

diff --git a/json.tcl b/json.tcl
new file mode 100644 (file)
index 0000000..659c152
--- /dev/null
+++ b/json.tcl
@@ -0,0 +1,84 @@
+namespace eval ten::json {
+
+  namespace eval deparse {
+
+    variable quotes [
+      list "\"" "\\\"" / \\/ \\ \\\\ \b \\b \f \\f \n \\n \r \\r \t \\t
+    ]
+
+    variable indent
+    variable indentBy 0
+    variable indentIncr
+    variable nl
+
+    proc indent_one {} {
+      variable indentIncr
+      variable indentBy [ expr $indentBy + $indentIncr ]
+      variable indent [ string repeat " " $indentBy ]
+    }
+
+    proc outdent_one {} {
+      variable indentIncr
+      variable indentBy [ expr $indentBy - $indentIncr ]
+      variable indent [ string repeat " " $indentBy ]
+    }
+
+    proc str {str} {
+      variable quotes
+      return \"[ string map $quotes $str ]\"
+    }
+
+    proc num {num} {
+      return $num
+    }
+
+    proc list {args} {
+      variable indent
+      variable nl
+      set out \[
+      indent_one
+      foreach el [lrange $args 0 end] {
+        append out $nl$indent
+        append out [ eval $el ],
+      }
+      outdent_one
+      append out $nl$indent\]
+      return $out
+    }
+
+    proc obj {args} {
+      variable indent
+      variable nl
+      set out \{
+      indent_one
+      dict for {k v} $args {
+        append out $nl$indent[ str $k ]:\ [ eval $v ],
+      }
+      outdent_one
+      append out $nl$indent\}
+    }
+
+    proc deparse {args} {
+      switch -regexp [lindex $args 0] {
+        ^num|str|obj|list$ -
+        default { error "Invalid JSON type [lindex $args 0]" }
+      }
+      return [ eval $args ]
+    }
+  }
+
+  proc deparse_json {data {indentIncr 2}} {
+    set deparse::indentBy 0
+    set deparse::indentIncr $indentIncr
+    if [expr $indentIncr == 0] {
+      set deparse::nl ""
+    } else {
+      set deparse::nl "\n"
+    }
+    namespace inscope deparse eval $data
+  }
+}
+
+puts [ ten::json::deparse_json {
+  list {str foo} {num 0} {obj __remote_object__ {str 512}}
+} 0 ]