关于循环使用 json2dict 转换的字典的想法

Thoughts on looping through a dict converted using json2dict

我正在尝试想出最好的方法来显示我使用 json2dict 转换的字典内部的两个值。以下是我的调用返回代码的基本格式:

{
"templates": [
    {
        "title": "Title1",
        "uuid": "123-456-789",
        "key_dont_need": "value"
    },
    {
        "key_dont_need": "value"
        "title": "Title2",
        "uuid": "acr-t54-g32",
    },
    {
        "title": "Network Scan",
        "key_dont_need": "value"
        "uuid": "5ge-534-3g3"
    }
  ]
}

我要做的是提取每个标题和 uuid。我设法让它拉出第一个 title/uuid 但在那之后我并没有取得太大的成功。这是我当前的代码(请根据需要销毁它,我仍在学习并且希望得到反馈):

package require rest
package require tls
package require json

::http::register https 443 ::tls::socket


proc login {url credentials} {
    append url /session
    set unformattedToken [dict get [::json::json2dict [::rest::post $url $credentials]] token]
    set token [format "token=%s" $unformattedToken] 
    return $token
}

proc logout {url config} {
    append url /session
    set logout [::rest::delete $url -headers $config]
}

proc get_scan_list {url config} {
    append url /scans
    set response [::rest::get $url -headers $config]
    return $response
}

proc get_scan_policies {url config} {
    append url /editor/policy/templates
    set policy_list [::rest::get $url -headers $config]]
    dict get [lindex [dict get [::json::json2dict $policy_list] templates] 0] title
}

set url https://127.0.0.1:8834
set credentials {username admin password myPassword}
set token [login $url $credentials]
dict set config headers X-Cookie $token
set scan_list [get_scan_list $url $config]
set scan_policies [get_scan_policies $url $config]

我正在尝试想出增加这些 uuid 的最佳方法,但我遇到了一些障碍。

以下是我尝试过的几种方法:

dict for {id templates} $policy_list {
        puts "Policy Name: $title"
        puts "Policy UUID: $uuid"
    }

我也在这里尝试过这个想法: http://wiki.tcl.tk/19941

但我也没有太多运气。从 Python 的角度来看,这基本上是我想要做的事情:

def get_policies():
"""
Get scan policies

Get all of the scan policies but return only the title and the uuid of
each policy.
"""

data = connect('GET', '/editor/policy/templates')

return dict((p['title'], p['uuid']) for p in data['templates'])

我开始怀疑我的问题是否与数据转换为 json2dict 后的存储方式有关?我可能会离开那里的基地。

编辑

就在我点击提交时,我设法让它与这个一起工作:

proc get_scan_policies {url config} {
    append url /editor/policy/templates
    set policy_list [::rest::get $url -headers $config]
    for {set i 0} {$i < 17} {incr i} {
        puts [dict get [lindex [dict get [::json::json2dict $policy_list] templates] $i] uuid]
        puts [dict get [lindex [dict get [::json::json2dict $policy_list] templates] $i] title]
    }
}

这是我的输出:

Policy Name: Title1
Policy UUID: 123-456-789
Policy Name: Title2
Policy UUID: acr-t54-g32
Policy Name: Network Scan
Policy UUID: 5ge-534-3g3

我在那里硬编码了计数,但很想看看是否有更好的方法可以做到这一点。

已更正 json:

set json {{
"templates": [
    {
        "title": "Title1",
        "uuid": "123-456-789",
        "key_dont_need": "value"
    },
    {
        "key_dont_need": "value",
        "title": "Title2",
        "uuid": "acr-t54-g32"
    },
    {
        "title": "Network Scan",
        "key_dont_need": "value",
        "uuid": "5ge-534-3g3"
    }
  ]
}}

转换为 Tcl dict:

package require json

set policy_list [::json::json2dict $json]

仅使用 titleuuid 键获取新的 dict

lmap item [dict get $policy_list templates] {
    dict filter $item key title uuid
}

打印 titleuuid 键的值:

foreach item [dict get $policy_list templates] {
    dict with item {
        puts "Policy Name: $title"
        puts "Policy UUID: $uuid"
    }
}

你必须从一个 json 对象开始,它有一个键 (templates) 和一个值,它是一个数组。数组中的每一项都是一个具有三个键(titleuuidkey_dont_need)的对象。要访问此结构中的内部值,您需要一个 dict 访问操作、一个列表 mapping/iteration 操作和每个项目的 dict 访问操作。

dict get $policy_list templates

让你进入外部对象。

foreach item ... script

让您遍历数组中的每一项;

lmap item ... script

让您 映射 每个项目,返回一个包含每个脚本评估结果的新列表。

dict filter dict-value key k1 k2 ...

创建一个 dict,由另一个 dict 的成员组成,这些成员的键与 k1k2、...参数命名的键匹配(它们可以有 glob 形式,例如 foo*).

dict with dict-variable script

(它也可以使用键,但不需要它们)基本上使用新创建的变量评估脚本,这些变量具有键的名称和值的值。

文档:dict, foreach, json package, lmap, lmap replacement, package, puts, set

除了硬编码 17,您可以尝试以下方法:

proc get_scan_policies {url config} {
    append url /editor/policy/templates
    set policy_list [::rest::get $url -headers $config]
    set len [llength $policy_list]
    for {set i 0} {$i < $len} {incr i} {
        puts [dict get [lindex [dict get [::json::json2dict $policy_list] templates] $i] uuid]
        puts [dict get [lindex [dict get [::json::json2dict $policy_list] templates] $i] title]
    }
}