TCL/C extension for parsing JSON
Contact: neophytos (at) gmail (dot) com
# Parse JSON string and return a simple TCL structure # ::tjson::json_to_simple json_string ::tjson::json_to_simple {{"a": 1, "b": true, "c": [1, 2, 3], "d": {"d1":"a", "d2":"b"}}} true => a 1 b 1 c {1 2 3} d {d1 a d2 b} # Parse JSON string and return a typed TCL structure # ::tjson::json_to_typed json_string ::tjson::json_to_typed {{"a": 1, "b": true, "c": [1, 2, 3], "d": {"d1":"a", "d2":"b"}}} => M {a {N 1} b {BOOL 1} c {L {{N 1} {N 2} {N 3}}} d {M {d1 {S a} d2 {S b}}}} # Serialize a typed TCL structure to JSON. # ::tjson::typed_to_json typed_spec ::tjson::typed_to_json {M {a {N 1} b {BOOL 1} c {L {{N 1} {N 2} {N 3}}} d {M {d1 {S a} d2 {S b}}}}} => {"a": 1, "b": true, "c": [1, 2, 3], "d": {"d1": "a", "d2": "b"}} # Escape JSON string # ::tjson::escape_json_string string ::tjson::escape_json_string "hello\nworld\n" => hello\"world\n
Here is an example of parsing and manipulating the JSON node:
package require tjson set node_handle [::tjson::parse { { "store": { "book": [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": "8.95" }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": "12.99" }, { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": "8.99" }, { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": "22.99" } ], "bicycle": { "color": "red", "price": "19.95" } } }}] set store_handle [::tjson::get_object_item $node_handle store] ::tjson::add_item_to_object $store_handle car [list M \ [list brand {S "Mercedes"} color {S blue} price {N 19876.57}]] set book_handle [::tjson::get_object_item $store_handle book] ::tjson::add_item_to_array $book_handle [list M \ [list \ category {S "fiction"} \ author {S "Fyodor Dostoevsky"} \ title {S "Brothers Karamazov"} \ isbn {S "0679410031"} \ price {N "22.19"}]] puts [::tjson::to_pretty_json $node_handle] ::tjson::destroy $node_handle
It is possible to perform JSONPath queries as follows:
set jsonpath {$.store..author} set item_handles [::tjson::query $handle $jsonpath] lmap x $item_handles {::tjson::to_simple $x}
Download this file: https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.json
package require tjson set fp [open "spec3.json"] set data [read $fp] close $fp puts [time {::tjson::destroy [::tjson::parse $data]} 1000]
=> 27935.83 microseconds per iteration