&|What|build JSON with tdom using '''''createNodeCmd'''''|& &|Requires|tdom 0.9.2|& &|tags|tdom|& &|reference|http://www.tdom.org/index.html/doc/trunk/doc/index.html|& &|Updated|03.07.2022|& ---- **Index** 1. Challenge 2. insufficient Approach 3. Issues and Improvements 4. improved Approvements 5. Summary 6. Discussion **Challenge** how to build a JSON like this: ====== { "aNumber": 0.123, "aNumberAsString": "0.123", "aString": "this is a String", "a key with spaces": "please take care on setting: dom setNameCheck 0", "aArray": ["a","b","c"], "aObject": { "foo":"that", "bar":"grill" }, "aObjectArray": [ { "foo": "objArray_01_foo", "bar": "objArray_01_bar", "array": ["five_01_a", "five_01_b", "five_01_c"] }, { "foo": "objArray_02_foo", "bar": "objArray_02_bar", "array": ["five_02_a", "five_02_b", "five_02_c"] } ] } ====== **insufficient Approach** ====== # # --- load tdom --- # package require tdom 0.9 ;# current version: 0.9.2 (May, 2022) puts "tdom: [package versions tdom]" # # http://www.tdom.org/index.html/file?name=tests/domjson.test&ci=release # # set doc [dom createDocumentNode root] # puts "asXML: [$root asXML -indent 4]" puts "asJSON: [$root asJSON -indent 4]" # # -- aNumber -- # set node_Number [$doc createElement "aNumber" NONE] $node_Number appendChild [$doc createTextNode 0.123 NUMBER] $root appendChild $node_Number # # -- aNumberAsString -- # set node_StringNum [$doc createElement "aNumberAsString" NONE] $node_StringNum appendChild [$doc createTextNode 0.123 NUMBER] $root appendChild $node_StringNum # # -- aString -- # set node_String [$doc createElement "aNumberString" NONE] $node_String appendChild [$doc createTextNode "0.123" NUMBER] $root appendChild $node_String # set node_String [$doc createElement "aString" NONE] $node_String appendChild [$doc createTextNode "this is a String" STRING] $root appendChild $node_String # # -- a key with spaces -- # # ... you have to disable namecheck first dom setNameCheck 0 set node_String [$doc createElement "a key with spaces" NONE] # [dom setNameCheck] == 1 ... brings this error # ERROR: Invalid tag name 'a key with spaces' # while executing # "$doc createElement "a key with spaces" NONE" # invoked from within # "set node_String [$doc createElement "a key with spaces" NONE]" # $node_String appendChild [$doc createTextNode "please take care on setting: dom setNameCheck 0" STRING] $root appendChild $node_String # # -- aArray -- # set node_Array [$doc createElement "aArray" ARRAY] $node_Array appendChild [$doc createTextNode "a" STRING] $node_Array appendChild [$doc createTextNode "b" STRING] $node_Array appendChild [$doc createTextNode "c" STRING] $root appendChild $node_Array # # # -- aObject -- # set node_Object [$doc createElement "aObject" OBJECT] # set node__Label [$doc createElement "foo" NONE] set node__Value [$doc createTextNode "that" STRING] $node_Object appendChild $node__Label $node__Label appendChild $node__Value # set node__Label [$doc createElement "bar" NONE] set node__Value [$doc createTextNode "grill" STRING] $node_Object appendChild $node__Label $node__Label appendChild $node__Value # $root appendChild $node_Object # # # -- aObjectArray -- # set node_ObjArray [$doc createElement "aObjectArray"] # set node__Obj_01 [$doc createElement "obj0001"] # set node__Label [$doc createElement "foo"] set node__Value [$doc createTextNode "objArray_01_foo" STRING] $node__Label appendChild $node__Value $node__Obj_01 appendChild $node__Label set node__Label [$doc createElement "bar"] set node__Value [$doc createTextNode "objArray_01_bar" STRING] $node__Label appendChild $node__Value $node__Obj_01 appendChild $node__Label # set node__Array [$doc createElement "array" ARRAY] $node__Array appendChild [$doc createTextNode "five_01_a" STRING] $node__Array appendChild [$doc createTextNode "five_01_b" STRING] $node__Array appendChild [$doc createTextNode "five_01_c" STRING] # $node__Obj_01 appendChild $node__Array # # set node__Obj_02 [$doc createElement "obj0002"] # set node__Label [$doc createElement "foo"] set node__Value [$doc createTextNode "objArray_02_foo" STRING] $node__Label appendChild $node__Value $node__Obj_02 appendChild $node__Label set node__Label [$doc createElement "bar"] set node__Value [$doc createTextNode "objArray_02_bar" STRING] $node__Label appendChild $node__Value $node__Obj_02 appendChild $node__Label # set node__Array [$doc createElement "array" ARRAY] $node__Array appendChild [$doc createTextNode "five_02_a" STRING] $node__Array appendChild [$doc createTextNode "five_02_b" STRING] $node__Array appendChild [$doc createTextNode "five_02_c" STRING] # $node__Obj_02 appendChild $node__Array # $node_ObjArray appendChild $node__Obj_01 $node_ObjArray appendChild $node__Obj_02 # # $root appendChild $node_ObjArray # # in the case of mixed OBJECT and ARRAYs you have to update the specific rendering $node_ObjArray jsonType ARRAY $node__Obj_01 jsonType OBJECT $node__Obj_02 jsonType OBJECT # puts "== \$resultJSON ====" puts [$doc asXML -indent 4] puts "== \$resultJSON ====" puts [$doc asJSON -indent 4] # ====== ... output of this script: ====== tdom: 0.9.2 asXML: asJSON: {} == $resultJSON ==== 0.123 0.123 0.123 this is a String please take care on setting: dom setNameCheck 0 abc that grill objArray_01_foo objArray_01_bar five_01_afive_01_bfive_01_c objArray_02_foo objArray_02_bar five_02_afive_02_bfive_02_c == $resultJSON ==== { "aNumber": "0.123", "aNumberAsString": "0.123", "aNumberString": "0.123", "aString": "this is a String", "a key with spaces": "please take care on setting: dom setNameCheck 0", "aArray": [ "a", "b", "c" ], "aObject": { "foo": "that", "bar": "grill" }, "aObjectArray": [ { "foo": "objArray_01_foo", "bar": "objArray_01_bar", "array": [ "five_01_a", "five_01_b", "five_01_c" ] }, { "foo": "objArray_02_foo", "bar": "objArray_02_bar", "array": [ "five_02_a", "five_02_b", "five_02_c" ] } ] } ====== **Issues and Imoprovements** ***wrong Value*** ====== this Result: "aNumber": "0.123" expected Result: "aNumber": 0.123 ====== ***complex code*** ... the given approach takes a lot of lines to create this result **improved Approach** use ====== dom createNodeCmd ====== to improve our code ====== # # --- load tdom --- # package require tdom 0.9 ;# current version: 0.9.2 (May, 2022) puts "tdom: [package versions tdom]" # # http://www.tdom.org/index.html/file?name=tests/domjson.test&ci=release # # # puts "== 01 == \$resultJSON ====" set doc [dom createDocumentNode root] # puts "asXML: [$root asXML -indent 4]" puts "asJSON: [$root asJSON -indent 4]" # # # our targetJSON includes nodes with predefined names: # "aNumber" "aString" "a key with spaces" "foo" "bar" # # ... lets predefine dom-commands to create these nodes # dom createNodeCmd -jsonType NONE elementNode aNumber dom createNodeCmd -jsonType NONE elementNode aNumberAsString dom createNodeCmd -jsonType NONE elementNode aString dom createNodeCmd -jsonType NONE elementNode "a key with spaces" dom createNodeCmd -jsonType NONE elementNode foo dom createNodeCmd -jsonType NONE elementNode bar dom createNodeCmd -jsonType NONE elementNode array dom createNodeCmd -jsonType ARRAY elementNode "aArray" dom createNodeCmd -jsonType OBJECT elementNode "aObject" dom createNodeCmd -jsonType ARRAY elementNode "aObjectArray" # # ... json distinguishs between # ... Arrays ["A","B","C"] and # ... Objects {"a": "A", "b": "B", "c":"C"} # dom createNodeCmd -jsonType NUMBER textNode jsonNumber dom createNodeCmd -jsonType STRING textNode jsonString # # set resultJSON [dom createDocumentNode] # puts "== 02 == \$resultJSON ====" puts [$resultJSON asJSON -indent 4] # $resultJSON appendFromScript { aNumber {jsonNumber 0.123} aNumberAsString {jsonString 0.123} aString {jsonString "this is a string"} "a key with spaces" {jsonString "It's possible."} aArray { jsonString a jsonString b jsonString c } aObject { foo {jsonString "that"} bar {jsonString "grill"} } aObjectArray { aObject { foo {jsonString "objArray_01_foo"} bar {jsonString "objArray_01_bar"} aArray { jsonString "five_01_a" jsonString "five_01_b" jsonString "five_01_c" } } aObject { foo {jsonString "objArray_02_foo"} bar {jsonString "objArray_02_bar"} aArray { jsonString "five_02_a" jsonString "five_02_b" jsonString "five_02_c" } } } } # # puts "== 03 == \$resultJSON ====" puts [$resultJSON asXML -indent 4] puts "== 03 == \$resultJSON == final ==" puts [$resultJSON asJSON -indent 4] # ====== ... output of this script: ====== tdom: 0.9.2 == 01 == $resultJSON ==== asXML: asJSON: {} == 02 == $resultJSON ==== {} == 03 == $resultJSON ==== 0.123 0.123 this is a string It's possible. abc that grill objArray_01_foo objArray_01_bar five_01_afive_01_bfive_01_c objArray_02_foo objArray_02_bar five_02_afive_02_bfive_02_c == 03 == $resultJSON == final == { "aNumber": 0.123, "aNumberAsString": "0.123", "aString": "this is a string", "a key with spaces": "It's possible.", "aArray": [ "a", "b", "c" ], "aObject": { "foo": "that", "bar": "grill" }, "aObjectArray": [ { "foo": "objArray_01_foo", "bar": "objArray_01_bar", "aArray": [ "five_01_a", "five_01_b", "five_01_c" ] }, { "foo": "objArray_02_foo", "bar": "objArray_02_bar", "aArray": [ "five_02_a", "five_02_b", "five_02_c" ] } ] } ====== **Summary** * enable creating a node as a number * createNodeCmd: ** define nodes with name and type ** create your JSON like it should look like at the end **Discussion** ... your comments [rattleCAD] 2022-07-03 ... you can improve this by replace: ====== dom createNodeCmd -jsonType NONE elementNode aNumber dom createNodeCmd -jsonType NONE elementNode aNumberAsString dom createNodeCmd -jsonType NONE elementNode aString dom createNodeCmd -jsonType NONE elementNode "a key with spaces" dom createNodeCmd -jsonType NONE elementNode foo dom createNodeCmd -jsonType NONE elementNode bar dom createNodeCmd -jsonType NONE elementNode array dom createNodeCmd -jsonType ARRAY elementNode "aArray" dom createNodeCmd -jsonType OBJECT elementNode "aObject" dom createNodeCmd -jsonType ARRAY elementNode "aObjectArray" ====== by ====== foreach {nodeName nodeType jsonType} { aNumber elementNode NONE aNumberAsString elementNode NONE aString elementNode NONE "a key with spaces" elementNode NONE foo elementNode NONE bar elementNode NONE array elementNode NONE "aArray" elementNode ARRAY "aObject" elementNode OBJECT "aObjectArray" elementNode ARRAY jsonNumber textNode NUMBER jsonString textNode STRING } { # dom createNodeCmd -jsonType STRING textNode jsonString # puts " -> dom createNodeCmd -jsonType [format {%-8s %-12s %s} $jsonType $nodeType $nodeName]" dom createNodeCmd -jsonType $jsonType $nodeType $nodeName } ======