Json 在TCL中的dict中创建dict列表
我被迫使用TCL来做一些事情,我需要创建一个json字符串,如下所示:Json 在TCL中的dict中创建dict列表,json,dictionary,tcl,Json,Dictionary,Tcl,我被迫使用TCL来做一些事情,我需要创建一个json字符串,如下所示: { "mainKey": "mainValue", "subKey": [{"key1":"value1"},{"key2":"value2"}]} compile_json {dict subKey list} finalDict 所以我试着这样做: set subDict1 [dict create key1 value1] set subDict2 [dict create key2 value2] set sub
{ "mainKey": "mainValue", "subKey": [{"key1":"value1"},{"key2":"value2"}]}
compile_json {dict subKey list} finalDict
所以我试着这样做:
set subDict1 [dict create key1 value1]
set subDict2 [dict create key2 value2]
set subDictList [list $subDict1 $subDict2]
set finalDict [dict create mainKey mainValue subKey $subDictList]
当我将此dict转换为json时,我得到:
{"mainKey":"mainValue", "subKey":{"key1 value1":{"key2":"value2"}}}
而不是要求:
{ "mainKey": "mainValue", "subKey": [{"key1":"value1"},{"key2":"value2"}]}
我做错了什么?首先,您必须了解TCL是一种非常无类型的语言。tcl中的列表和目录到底是什么 在Tcl中,列表是一个格式正确的字符串,其中列表的每个成员由空格(空格、制表符或换行符)分隔,如果项目包含的数据包含空格,则可以通过以下方式进行转义:
"this is a list\ of\ four\ items"
”
分组:
{this is a "list of four items"}
{this is a {list of four items}}
{}
分组:
{this is a "list of four items"}
{this is a {list of four items}}
# data is plain old tcl values
# spec is defined as follows:
# {string} - data is simply a string, "quote" it if it's not a number
# {list} - data is a tcl list of strings, convert to JSON arrays
# {list list} - data is a tcl list of lists
# {list dict} - data is a tcl list of dicts
# {dict} - data is a tcl dict of strings
# {dict xx list} - data is a tcl dict where the value of key xx is a tcl list
# {dict * list} - data is a tcl dict of lists
# etc..
proc compile_json {spec data} {
while [llength $spec] {
set type [lindex $spec 0]
set spec [lrange $spec 1 end]
switch -- $type {
dict {
lappend spec * string
set json {}
foreach {key val} $data {
foreach {keymatch valtype} $spec {
if {[string match $keymatch $key]} {
lappend json [subst {"$key":[
compile_json $valtype $val]}]
break
}
}
}
return "{[join $json ,]}"
}
list {
if {![llength $spec]} {
set spec string
} else {
set spec [lindex $spec 0]
}
set json {}
foreach {val} $data {
lappend json [compile_json $spec $val]
}
return "\[[join $json ,]\]"
}
string {
if {[string is double -strict $data]} {
return $data
} else {
return "\"$data\""
}
}
default {error "Invalid type"}
}
}
}
(有关JSON解析的原始实现和讨论,请参见)
因为tcl永远无法正确猜测“字符串”是什么,所以我选择向函数提供格式字符串,以便正确解释tcl数据结构。例如,使用上面的函数编译dict,您可以这样调用它:
{ "mainKey": "mainValue", "subKey": [{"key1":"value1"},{"key2":"value2"}]}
compile_json {dict subKey list} finalDict
我恳求tcllib维护人员窃取我的代码,因为我仍然相信这是在tcl中处理JSON的正确方法,但到目前为止,它仍然不在tcllib中
顺便说一句:我将上面的代码授权为公共域,如果您愿意,您或任何人都可以声称它是完全的作者。说Tcl是一种无类型语言并不是完全错误的,因为Tcl程序中的数据对象类型在代码中没有完全表达出来,甚至在内部表示数据对象的
Tcl_Obj
结构中也不总是这样。尽管如此,类型在Tcl程序中并不是不存在的,只是类型系统在Tcl中的侵入性比在大多数其他编程语言中要小得多
Tcl程序中完整的类型定义来自程序执行时代码和数据对象的动态组合。解释器信任您告诉它您希望数据对象的行为
作为一个例子,考虑下面的字符串:
set s {title: Mr. name: Peter surname: Lewerin}
这是字符串、数组还是字典?事实上,所有这些。(至少它不是整数、双精度或布尔值以及其他可能的Tcl类型。)
使用此字符串,我可以回答许多问题:
告诉我你的名字
有礼貌的人怎么称呼你
你的姓是什么
在这里,我使用相同的字符串作为字符串、字典和数组。所有三种类型的对象都使用了相同的字符串表示,正是我对其使用的操作决定了当时对象的类型
类似地,文本1
可以表示整数1、单个字符串1或布尔真值。没有办法指定你指的是哪种类型的1,但也没有必要,因为口译员不会抱怨歧义
因为Tcl不存储完整的类型信息,所以很难序列化任意数据对象集合。但这并不意味着Tcl不能很好地处理序列化:您只需要向数据中添加注释
此字符串:
di [dm [st mainKey] [st mainValue]] [dm [st subKey] [ar [di [dm [st key1] [st value1]]] [di [dm [st key2] [st value2]]]]]
可以输入Tcl解释器,并给出di
、dm
、st
和ar
(我打算分别表示“dictionary”、“dictionary member”、“string”和“array”)的正确定义,我可以让字符串构造一个与问题中的字典结构等效的字典结构,或者是这样一个对象的字符串表示,仅仅是一个简单的键和值列表,或者XML,或者JSON,等等。通过使用名称空间和/或从解释器,我甚至可以在各种形式之间动态切换。我不会提供所有表单的示例,只提供JSON:
proc di args {return "{[join $args {, }]}"}
proc st val {return "\"$val\""}
proc ar args {return "\[[join $args {, }]]"}
proc dm {k v} {return "$k: $v"}
输出变为:
{"mainKey": "mainValue", "subKey": [{"key1": "value1"}, {"key2": "value2"}]}
本例使用Tcl解释器的命令嵌套来定义数据的结构。Tcl甚至不需要这样做:一个令牌类和令牌列表(如扫描器将发出的令牌)就足够了:
< : ' mainKey ' mainValue : ' subKey ( < : ' key1 ' value1 > < : ' key2 ' value2 > ) >
另一种方法是创建常规的Tcl结构,并根据类型规范将其转换(“编译”)为压缩数据:
set subDict1 [dict create key1 value1]
set subDict2 [dict create key2 value2]
set subDictList [list $subDict1 $subDict2]
set finalDict [dict create mainKey mainValue subKey $subDictList]
huddle compile {dict mainKey string subKey {list {dict * string}}} $finalDict
最后一个命令的结果与上一个示例中最后一个huddle create
命令的结果相同
文档:,,,,,,您使用什么命令从
finalDict
创建JSON字符串?我使用的是JSON包。set myJson[::json::dict2json$finalDict]感谢您的深入了解。我也在怀疑同样的事情。但问题是怎么做
package require huddle
# -> 0.1.5
set subDict1 [huddle create key1 value1]
# -> HUDDLE {D {key1 {s value1}}}
set subDict2 [huddle create key2 value2]
# -> HUDDLE {D {key2 {s value2}}}
set subDictList [huddle list $subDict1 $subDict2]
# -> HUDDLE {L {{D {key1 {s value1}}} {D {key2 {s value2}}}}}
set finalDict [huddle create mainKey mainValue subKey $subDictList]
# -> HUDDLE {D {mainKey {s mainValue} subKey {L {{D {key1 {s value1}}} {D {key2 {s value2}}}}}}}
huddle jsondump $finalDict {} {}
# -> {"mainKey":"mainValue","subKey":[{"key1":"value1"},{"key2":"value2"}]}
set subDict1 [dict create key1 value1]
set subDict2 [dict create key2 value2]
set subDictList [list $subDict1 $subDict2]
set finalDict [dict create mainKey mainValue subKey $subDictList]
huddle compile {dict mainKey string subKey {list {dict * string}}} $finalDict