Python以不同的方式解析JSON对象

时间:2018-10-10 06:21:42

标签: python json python-3.x jsonparser

我正在处理一个python项目,我们在其中从用户那里得到一些输入。 我们实际上正在从事微服务部署。用户需要提供以下内容的地方:

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

2):用户将提供一个JSON对象,其中将提及此存储库的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。 我该如何克服这个问题?

谢谢!

3 个答案:

答案 0 :(得分:0)

JSON无效的原因是,JSON数组中不能包含名称/值对。 This页告诉您一个数组可以是:

  

用逗号分隔的未命名值列表(简单或复杂),用括号括起来

下面的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中的对象。

答案 1 :(得分:0)

您认为太复杂了。

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

完成。

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

每当你想写作

for thing in range(len(some_list)):

停止,然后写

for thing in some_list:

相反。

答案 2 :(得分:0)

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

首先,默认情况下,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']

因此,在两种情况下,我们首先拥有nodeservicepyservice的顺序相同。