【问题标题】:Python, jsonpath: How do I parse with jsonpath correctly?Python,jsonpath:如何正确解析 jsonpath?
【发布时间】:2018-02-05 18:47:47
【问题描述】:

我有一个实施问题...

#!/usr/bin/python

#This is the API for BTC price request. 
# Average all the amounts, and push that to the program

import json
import urllib.request
from jsonpath_rw import parse as parse_jsonpath

class BtcAPI:

    def __init__(self, url, api_id, json_key):
        self.url = url
        self.api_id = api_id
        self.json_key = json_key

    def btc_api_call(self):

        hdr = { 'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)' }
        req = urllib.request.Request(self.url, headers=hdr)
        readdata = urllib.request.urlopen(req)
        json_data = readdata.read()

        json_dict = json.loads(json_data)
        results = parse_jsonpath(self.json_key).find(json_dict)
        print(results)


class Price:


    def __init__(self, api_id, url, json_key):

        self.api_id = api_id
        self.url = url
        self.json_key = json_key

    def pass_for_request(self):

        get_price = BtcAPI(self.url, self.api_id, self.json_key)
        get_price.btc_api_call()


def Coindesk():
    coindesk = Price("coindesk","https://api.coindesk.com/v1/bpi/currentprice.json","time.updated")
coindesk.pass_for_request()

为“json_key”传递的值是“bpi.USD.rate_float”...在这个 url 中。它被传递给一个名为“Price”的类,该类创建传递给包含上述代码的类的变量。

coindesk = Price("coindesk","api.coindesk.com/v1/bpi/currentprice.json", "bpi.USD.rate_float")

这是我所针对的 json...试图获取 rate_float 键:

{
  "time": {
    "updated": "Feb 5, 2018 18:34:00 UTC",
    "updatedISO": "2018-02-05T18:34:00+00:00",
    "updateduk": "Feb 5, 2018 at 18:34 GMT"
  },
  "disclaimer": "This data was produced from the CoinDesk Bitcoin Price Index (USD). Non-USD currency data converted using hourly conversion rate from openexchangerates.org",
  "chartName": "Bitcoin",
  "bpi": {
    "USD": {
      "code": "USD",
      "symbol": "$",
      "rate": "7,004.9588",
      "description": "United States Dollar",
      "rate_float": 7004.9588
  }
}

当我运行程序时,它使用“bpi.USD.rate_float”向我发送整个 json 文件的输出,而不是我试图通过 jsonpath 定位的特定键 我正在使用 jsonpath_rw。

如何使用 jsonpath 有效地定位 rate_float 键?

【问题讨论】:

  • parse_jsonpathjsonpath_rw 中不存在。它有什么作用? time.updated 与您的其余问题有什么关系? “在这个网址内”?什么网址?如果我们看不到该类的任何代码,您认为Price 行将如何帮助我们?它甚至相关吗?与其向我们提供您认为相关的随机代码片段,不如给我们一个最小的、完整的、可重现问题的工作示例:stackoverflow.com/help/mcve。您可能误解了某些东西的工作原理,或者我们看不到的代码部分存在错误。
  • 对不起。 time.updated 是一个错字。我用它来测试我是否可以针对另一个键。它应该是 bpi.USD.rate_float。
  • 已更新以包含所有代码。我认为没有必要包含整个代码主体,因为我怀疑问题是语法错误……无需大量测试就可以相对容易地解决。
  • 请注意我提到的“最小”。您无需向我们展示您的所有代码。在演示问题的同时,您可以删除多少代码?例如。如果将所有代码替换为from jsonpath_rw import parse as parse_jsonpath; results = parse_jsonpath("bpi.USD.rate_float").find({your_actual_dict_goes_here}); print(results)(用换行符而不是;)会发生什么?你还有同样的问题吗?
  • 我在这里要做的唯一一件事就是帮助您找出问题所在。如果我建议的最小代码确实按您的预期工作,那么您的问题不在于jsonpath,而在于某处else。例如。您确定您发出的 HTTP 请求实际上返回了您期望的数据吗?

标签: python json jsonpath


【解决方案1】:

问题是您可能认为results 包含来自 Python dict 的纯字符串值。

这实际上不是jsonpath_rw 返回的内容。如果您查看 https://github.com/kennknowles/python-jsonpath-rw 中的示例,您会看到它确实如此,例如

[match.value for match in jsonpath_expr.find({'foo': [{'baz': 1}, {'baz': 2}]})]

正如它进一步提到的那样:

JsonPath.find 的结果提供了详细的上下文和路径数据,因此很容易遍历父对象,打印数据的完整路径,并生成自动 ID。

find 实际上返回一个包含上下文信息的对象列表。如果您想要的只是字符串值,并且您只希望为您的 JSONPath 表达式获得一个返回值,那么您需要执行以下操作:

results = parse_jsonpath(self.json_key).find(json_dict)
print(results[0].value)

【讨论】:

  • 谢谢。这很有帮助。因此,Jsonpath 不能成为解决方案,因为我需要能够通过键动态访问结果,而不是对索引进行硬编码。
  • 我有一个困惑的问题,但是......为什么它会转储我请求的 json 文件的全部内容?如果没有解析功能,那么 jsonpath 的意义何在?
  • 您不需要对任何索引进行硬编码。您还可以遍历结果,就像我从“文档”中获取的示例一样。它在list comprehension 中执行此操作。而且它不会简单地转储 json 文件的全部内容。它返回一个对象列表。这些对象中的每一个都包含您所追求的值以及一个上下文对象,它允许您进行后处理,例如,查找您找到的值的父级或兄弟级。
  • 我绝对是愚蠢的。你提供了一个完美的解决方案,我需要做的就是仔细检查它。感谢您的亲切,感谢您的帮助!
【解决方案2】:

这里有一个工作 Python 3 方法:

def json_by_jsonpath():
    v_json     = "{\"_id\":{\"oid\":\"55561331552632234577\"},\"profilePatId\":\"123456\",\"patientPatId\":\"123456\",\"comboOrder\":false,\"globalOrderCode\":{\"$numberInt\":\"1\"},\"orderRefNum\":\"621980991862\",\"functionality\":{\"$numberInt\":\"38\"},\"rxType\":{\"$numberInt\":\"1\"},\"orderStoreNum\":\"59382\",\"orderChannel\":\"RR_EM\",\"orderChannelDtls\":\"QULL\",\"scriptDetailRetail\":[{\"rxNum\":{\"$numberInt\":\"274879\"},\"rxStoreNum\":{\"$numberInt\":\"59382\"},\"autoRefillEnabled\":false,\"autoRefillEligible\":false,\"insuranceAvailable\":false,\"sddDrugEligible\":false,\"drugQty\":{\"$numberInt\":\"0\"},\"deliveryInd\":\"1\",\"deliveryComments\":\"Ring bell and drop of in box. This comment is for SDD notes\",\"additionalComments\":\"Please call my insurance and this comment is on notes section\",\"appCode\":{\"$numberInt\":\"291\"}},{\"rxNum\":{\"$numberInt\":\"447902\"},\"rxStoreNum\":{\"$numberInt\":\"59382\"},\"autoRefillEnabled\":false,\"autoRefillEligible\":false,\"insuranceAvailable\":false,\"sddDrugEligible\":false,\"drugQty\":{\"$numberInt\":\"0\"},\"deliveryInd\":\"1\",\"deliveryComments\":\"Ring bell and drop of in box. This comment is for SDD notes\",\"additionalComments\":\"Please call my insurance and this comment is on notes section\",\"appCode\":{\"$numberInt\":\"100\"}}],\"_class\":\"com.rx.repositories.xOrderRetail\"}"


v_jsonpath =  '$._id.oid'  #'$.patientPatId'

        myjson = json.loads(v_json)
    #print(myjson)
    #result_list = [match.value for match in v_jsonpath.find(v_json)]
    #print(result_list)
    json_tag_val = parse(v_jsonpath).find(myjson)
    print(json_tag_val)

    return json_tag_val[0].value

【讨论】:

  • 我认为您指的是一个名为 'jsonpath-ng' (pypi.org/project/jsonpath-ng) 的库。这不是 Python3 的内置功能。事实上,该库也支持 Python 2.7。对于未来的 cmets:请添加您的导入和所有使用的库。谢谢。
猜你喜欢
  • 2022-01-02
  • 1970-01-01
  • 2023-02-23
  • 2018-01-27
  • 2017-12-21
  • 1970-01-01
  • 2017-02-05
  • 2016-02-05
  • 2022-01-05
相关资源
最近更新 更多