0

我想使用关系数据库来分析来自 Songkick 的JSON API 的本地事件信息。

中的事件对象复杂且嵌套很深,因此我想过滤和展平事件对象并将它们转换为 CSV,以便我可以使用标准工具加载它们。

我可以使用 jq 过滤和展平事件吗?

来自 API 的典型响应太大,无法在此处显示。我将展示一个具有相同相对结构的简化版本。

将过滤器.resultsPage.results.event[]应用于响应会产生这样的事件对象流。

{
  "start": {
    "date": "2014-10-28"
  },
  "performance": [
    {
      "artist": {
        "displayName": "James Keelaghan",
        "identifier": [
          {
            "mbid": "08e5954e-efc0-4a95-95ac-d74cca5b79ff"
          }
        ]
      }
    }
  ],
  "venue": {
    "displayName": "Live At The Star"
  }
}
{
  "start": {
    "date": "2014-10-28"
  },
  "performance": [
    {
      "artist": {
        "displayName": "Katy B",
        "identifier": [
          {
            "mbid": "2df30b6c-997d-4c3f-abb5-5e0d6317ea57"
          }
        ]
      }
    },
    {
      "artist": {
        "displayName": "Becky Hill",
        "identifier": [
          {
            "mbid": "27bc6f5b-4585-49ab-8d7d-c62b59f5f010"
          }
        ]
      }
    }
  ],
  "venue": {
    "displayName": "O2 ABC"
    }
}

接下来,我想为性能列表中的每个对象生成一个输出对象。这些新对象应具有包含事件对象的属性,例如日期和地点。

该示例的正确输出如下所示。

{
  "venue_name": "Live At The Star",
  "artist_mbid": "08e5954e-efc0-4a95-95ac-d74cca5b79ff",
  "artist_name": "James Keelaghan",
  "start_date": "2014-10-28"
}
{
  "venue_name": "O2 ABC",
  "artist_mbid": "2df30b6c-997d-4c3f-abb5-5e0d6317ea57",
  "artist_name": "Katy B",
  "start_date": "2014-10-28"
}
{
  "venue_name": "O2 ABC",
  "artist_mbid": "2df30b6c-997d-4c3f-abb5-5e0d6317ea57",
  "artist_name": "Becky Hill",
  "start_date": "2014-10-28"
}

如果我忽略 mbid,这个 jq 过滤器会给我我想要的。

{
  start_date: .start.date,
  artist_name: .performance[].artist.displayName,
  venue_name: .venue.displayName
}

结果看起来像这样。

{
  "venue_name": "Live At The Star",
  "artist_name": "James Keelaghan",
  "start_date": "2014-10-28"
}
{
  "venue_name": "O2 ABC",
  "artist_name": "Katy B",
  "start_date": "2014-10-28"
}
{
  "venue_name": "O2 ABC",
  "artist_name": "Becky Hill",
  "start_date": "2014-10-28"
}

我也尝试了这个过滤器来获得 mbid。

{
  start_date: .start.date,
  artist_name: .performance[].artist.displayName,
  artist_mbid: .performance[].artist.identifier[].mbid,
  venue_name: .venue.displayName
}

结果看起来像这样。

{
  "venue_name": "Live At The Star",
  "artist_mbid": "08e5954e-efc0-4a95-95ac-d74cca5b79ff",
  "artist_name": "James Keelaghan",
  "start_date": "2014-10-28"
}
{
  "venue_name": "O2 ABC",
  "artist_mbid": "2df30b6c-997d-4c3f-abb5-5e0d6317ea57",
  "artist_name": "Katy B",
  "start_date": "2014-10-28"
}
{
  "venue_name": "O2 ABC",
  "artist_mbid": "27bc6f5b-4585-49ab-8d7d-c62b59f5f010",
  "artist_name": "Katy B",
  "start_date": "2014-10-28"
}
{
  "venue_name": "O2 ABC",
  "artist_mbid": "2df30b6c-997d-4c3f-abb5-5e0d6317ea57",
  "artist_name": "Becky Hill",
  "start_date": "2014-10-28"
}
{
  "venue_name": "O2 ABC",
  "artist_mbid": "27bc6f5b-4585-49ab-8d7d-c62b59f5f010",
  "artist_name": "Becky Hill",
  "start_date": "2014-10-28"
}

每个对象看起来都不错,但是它们太多了!“Katy B”和“Becky Hill”对象被复制。

在 jq 中执行此操作的正确方法是什么?

4

1 回答 1

1

这个过滤器应该工作:

.resultsPage.results.event | map(
    {
        venue_name: .venue.displayName,
        start_date: .start.date
    }
    +
    (.performance[].artist | {
        artist_mbid: .identifier[].mbid,
        artist_name: .displayName
    })
)

尽管这些字段的顺序不同,但如果需要,您可以随时重新排序:

[
  {
    "venue_name": "Live At The Star",
    "start_date": "2014-10-28",
    "artist_mbid": "08e5954e-efc0-4a95-95ac-d74cca5b79ff",
    "artist_name": "James Keelaghan"
  },
  {
    "venue_name": "O2 ABC",
    "start_date": "2014-10-28",
    "artist_mbid": "2df30b6c-997d-4c3f-abb5-5e0d6317ea57",
    "artist_name": "Katy B"
  },
  {
    "venue_name": "O2 ABC",
    "start_date": "2014-10-28",
    "artist_mbid": "27bc6f5b-4585-49ab-8d7d-c62b59f5f010",
    "artist_name": "Becky Hill"
  }
]

您正在尝试为每个对应对象创建一个对象,performance因此您必须在开始收集结果之前将其压平一点。

于 2014-10-31T02:28:23.117 回答