从json输出中检索单个值?

时间:2018-05-07 21:29:59

标签: python json http curl

我有一个curl命令的json输出,我想得到一个值,但无法弄清楚如何做到这一点。我试图获得" X-Subject-Token"如下所示。

阅读类似的答案,我发现我可以使用json.load(sys.stdin)['X-Subject-Token']'。我试着运行下面的代码段......

$ curl -v -s -X POST https://host.com:13000/v3/auth/tokens?nocatalog \
       -H "Content-Type: application/json" 
       -d '{\
            "auth": {\
                "identity": {\
                    "methods": [\
                        "password"\
                    ],\
                    "password": {\
                        "user": {\
                            "domain": {\
                                "name": "'"$OS_USER_DOMAIN_NAME"'"\
                            },\
                            "name": "'"$OS_USERNAME"'",\
                            "password": "'"$OS_PASSWORD"'"\
                        }\
                    }\
                },\
                "scope": {\
                    "project": {\
                        "domain": {\
                            "name": "'"$OS_PROJECT_DOMAIN_NAME"'"\
                        },\
                        "name": "'"admin"'"\
                    }\
                }\
            }\
        }' | \
    python -m json.tool | \
    python -c 'import sys, json; print json.load(sys.stdin)['X-Subject-Token']'

...这给了我以下错误:

File "<string>", line 1, in <module>
KeyError: 'X-Subject-Token' 

试图替换单引号的双引号......

print json.load(sys.stdin)["X-Subject-Token"]'

...得到一个不同的错误:

NameError: name 'X' is not defined.

这是我尝试从中提取的输出的片段:

> Accept: */*
> Content-Type: application/json
> Content-Length: 245
> 

} [data not shown]
* upload completely sent off: 245 out of 245 bytes
< HTTP/1.1 201 Created
< X-Subject-Token: xxxxxxxxxxxxxxxxxxxxxxx
< Vary: X-Auth-Token
< Content-Type: application/json
< Content-Length: 489

我如何获得X-Subject-Token

我也尝试过grep和awk,我有更多的经验,但Python似乎是最干净的。

2 个答案:

答案 0 :(得分:2)

似乎@jwodder指出的情况:X-Subject-Token不是JSON的一部分,而是HTTP标头之一。

当您发出HTTP请求时,响应会附带一个正文和一系列标题。标头对于服务器和浏览器正常通信很重要;身体是我们通常想要的信息。由于标题通常(但并非总是)仅与服务器和浏览器相关,因此默认情况下curl仅为我们提供正文。在这里,我将使用一些随机JSON作为示例:

$ curl -X GET https://pastebin.com/raw/S5bxekgg
{"foo": "bar", "a": 2}

身体如此相关,你甚至相信你需要的信息就在其中 - 但事实并非如此!它在标题中。在这种情况下,我们还需要curl来为我们提供标题。这很容易,我们只需要给它-i选项:

$ curl -i -X GET https://pastebin.com/raw/S5bxekgg
HTTP/1.1 200 OK
Date: Mon, 07 May 2018 23:12:36 GMT
Content-Type: text/plain; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Set-Cookie: __cfduid=d570bd74e5f34b1ef0d5fe4658ba5e0461525734756; expires=Tue, 07-May-19 23:12:36 GMT; path=/; domain=.pastebin.com; HttpOnly
Cache-Control: public, max-age=1801
Access-Control-Allow-Origin: *
Vary: Accept-Encoding
X-XSS-Protection: 1; mode=block
CF-Cache-Status: HIT
Expires: Mon, 07 May 2018 23:42:37 GMT
Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Server: cloudflare
CF-RAY: 41775f564ca44bbd-GRU

{"foo": "bar", "a": 2}

现在我们有更多信息!唉,我的示例中没有您想要的X-Subject-Token标题,因此我将使用另一个标题:X-XSS-Protection

但它不在JSON中;我们怎么得到它?好吧,它更容易:使用shell!就个人而言,我会为我想要的标题寻找:

$ curl --silent -i -X GET https://pastebin.com/raw/S5bxekgg | grep X-XSS-Protection
X-XSS-Protection: 1; mode=block

一旦我拥有它,我就会使用cut取出值:

$ curl --silent -i -X GET https://pastebin.com/raw/S5bxekgg | grep X-XSS-Protection | cut -d: -f2
1; mode=block

它只是其中一种选择!我们甚至不需要Python!

所以,如果我的假设是正确的,问题不是Python,是你把HTTP响应头与HTTP响应体混淆了。如果你正在处理很多概念,那可能会有些混乱,但实践中无法解决;)

答案 1 :(得分:2)

X-Subject-Token是响应中的http标头。您可以使用curl的const namesHardest = ['emIly jack sMith', 'angeliNA Jolie', 'braD piTt']; let conv=Array.from(namesHardest,a=>a.toLowerCase().replace(/\b[a-z]/g, function(letter) { return letter.toUpperCase(); })) console.log(conv);标志将响应标头打印到stdout。然后你只需使用例如awk提取它。

--include
相关问题