【问题标题】:Python Parse JSON objects in Different WayPython以不同的方式解析JSON对象
【发布时间】:2018-10-10 06:21:41
【问题描述】:

我正在开发一个 python 项目,我们正在从用户那里获得一些输入。 实际上,我们正在研究微服务部署。其中用户需要提供以下内容:

1):用户将提供一个 GitHub 存储库,其中将包括他想要在特定目录中部署的所有微服务。 例如,我们在 GitHub 存储库中有一个目录结构,如下所示: mysvcs |----nodeservice |----pyservice

2):用户将提供一个 JSON 对象,他将在其中提及此 repo 的 URL 以及这些微服务的一些其他信息,如下所示:

{
  "repo_url": "https://github.com/arycloud/mysvcs.git",

  "services":[
        {
        "name": "pyservice",
        "routing": {
          "path": "/",
          "service": "pyservice",
          "port": "5000"
        }
      },
      {
        "name": "nodeservice",
        "routing": {
          "path": "/",
          "service": "nodeservice",
          "port": "8080"
        }
      }
        ]
}

然后我们从 GitHub 存储库中读取所有服务并使用它们的目录来读取源代码。与此同时,我们正在解析 JSON 对象以获取有关这些服务的一些信息。

我们正在阅读这样的回购:

tempdir = tempfile.mkdtemp()
saved_unmask = os.umask(0o077)
out_dir = os.path.join(tempdir)
Repo.clone_from(data['repo_url'], out_dir)
list_dir = os.listdir(out_dir)
print(list_dir)
services = []
for svc in range(0, len(data['services'])):
    services.append(list_dir[svc])

print(services)

根据我们上面的例子,它会返回:

['nodesvc', 'pyservice']

但是当我们读取 JSON 对象时,用户以不同的顺序而不是字母顺序提到了服务,所以当我们使用上述数组循环服务时,我们试图对 JSON 对象服务使用相同的索引,并且克隆 GitHub 存储库后的目录列表,但由于顺序不同,它会交换数据。

这是一个示例代码:

def my_deployment(data):
    # data is JSON object
    # Clone github repo and grab Dockerfiles
    tempdir = tempfile.mkdtemp()
    saved_unmask = os.umask(0o077)
    out_dir = os.path.join(tempdir)
    Repo.clone_from(data['repo_url'], out_dir)
    list_dir = os.listdir(out_dir)
    print(list_dir)
    services = []
    for svc in range(0, len(data['services'])):
        services.append(list_dir[svc])
    print(services)
    for service in range(len(services)):
        # Here i need to use the data from JSON object for current service 
        data['services'][service]['routing']['port']
        # Here it's using the data of **pyservice** instead of **nodeservice** and vice versa.

重要提示:GitHub 中的服务顺序是 ['nodeservices', 'nodeservices'],但在 JSON 对象中,用户可以按不同的顺序提及他的服务,例如 pyservices, nodeservices。那么当我们循环遍历时,我们如何同步这两个源的顺序呢?这是主要问题。

我已经尝试过以这种方式更改我的 JSON 对象的结构:

"services":[
    "pyservice": {
      "routing": {
        "path": "/",
        "service": "pyservice",
        "port": "5000"
      }
    },
    "nodeservice": {
      "routing": {
        "path": "/node",
        "service": "nodeservice",
        "port": "8080"
      }
    }
]

但上面写着syntax is not correct。 我该如何克服这个问题?

提前致谢!

【问题讨论】:

  • 你忘了把json里的[]改成{}
  • 嗨 @shadowtalker,它是 JSON 对象数组。
  • 如果你在JSON validator 中运行你的代码,你会发现它是无效的。
  • 嗨@VilleKoo,哪一个?我已经发布了 2 个版本的 JSON 对象,第一个是有效的,第二个不是我在问题中提到的。
  • @AbdulRehman 最底层

标签: python json python-3.x jsonparser


【解决方案1】:

你想的太复杂了。

for svc in data['services']:
    print(svc['name'], svc['routing']['port'])

完成。

一般观察:您似乎坚持使用循环索引。不。 Python 循环没有索引是件好事。

每当你想写作时

for thing in range(len(some_list)):

停止,然后写

for thing in some_list:

改为。

【讨论】:

  • 嗨@Tomalak,问题是两个地方的服务顺序不同。我们可以按字母顺序将 JSON 对象中的服务数组重新排序吗?它将与 GitHub repo 中的订单匹配。
  • 哪两个地方?首先不要构建svc_list 变量,你很好。 data['services'] 是您的服务列表。
  • 一个是Github repo,另一个是JSON对象数组。
  • 我不明白。您有一个包含所有相关信息的 svc 对象。名称,端口,随便什么。服务 name 与 repo 中的目录名称完全匹配。你还需要什么其他?
【解决方案2】:

JSON 无效的原因是 JSON 数组中不能有名称值对。 Thispage 告诉你一个数组可以是:

以逗号分隔的未命名值列表,简单或复杂,括在括号中

下面的 JSON 有用吗?

{
  "repo_url": "https://github.com/arycloud/mysvcs.git",

  "services":[
    {
      "pyservice": {
        "routing": {
          "path": "/",
          "service": "pyservice",
          "port": "5000"
        }
      }
    },
    {
      "nodeservice": {
        "routing": {
          "path": "/node",
          "service": "nodeservice",
          "port": "8080"
        }
      }
    }
  ]
}

如果您希望services 按字母顺序排序,您可以执行以下操作:

services = data["services"]

b = {}
for node in services:
  b.update(dict(node))

alphabetical_list = sorted(b)

注意:

这会为您提供一个列表['nodeservice', 'pyservice'],然后您可以使用它来获取b 中的对象。

【讨论】:

  • 嗨@NeRa,但是我们如何将这个JSON数组的顺序同步到来自Github repo的目录列表['nodesvc', 'pyservice']的顺序?这是主要问题。因为即使这样我们也需要使用索引来循环服务数组。
  • 我已经用字母顺序更新了我的答案。
【解决方案3】:

我们可以使用以下方法来解决此订单同步问题:

首先,GitHub 存储库中的目录顺序默认按字母顺序排列,因此如果我们对 JSON 对象中的服务数组进行排序,我们将能够为两个源获得相同的索引。甚至确保我们可以按字母顺序对这两个来源进行排序。

代码如下: 首先将 JSON 对象的 services 数组排序为:

data['services'] = sorted(data["services"], key=lambda d: d["name"])

通过考虑问题中的示例,它将给我们:

services = [
   {"nodeservice": {
     "A": "B"
     }
   },
   {"pyservice":{
     "X": "Y"
    }
   }
]

然后我们将从 GitHub 存储库中对目录列表进行排序,如下所示:

Repo.clone_from(data['repo_url'], out_dir)
list_dir = os.listdir(out_dir)
print(list_dir)
services = []
for svc in range(0, len(data['services'])):
    services.append(list_dir[svc])

services.sort()
print(services)

根据上面问题中的示例,它将给我们:['nodeservice', 'pyservice']。

所以,在这两种情况下,nodeservice 先是pyservice,表示相同的顺序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多