如何使用jq将JSON解析为单个嵌套对象?

时间:2019-07-24 15:39:57

标签: json jq

我正在尝试使用jq解析JSON文件,但无法正确处理。如何将以下JSON解析为:

  • 单个嵌套对象,并添加其他顶级键(示例中为“城市”,“ uppsala”和“位置”)
  • 使用键name的值作为对象的键吗?

(源json的缩写):

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "name": "Uppsala domkyrka"
      },
      "geometry": {
        "coordinates": [
          17.6336159,
          59.8581466
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "name": "Uppsala moské"
      },
      "geometry": {
        "coordinates": [
          17.6382165,
          59.874003
        ]
      }
    }
  ]
}

我正在尝试将其解析为这种格式

{
  "cities": {
    "uppsala": {
      "locations": {
        "Uppsala domkyrka": {
          "name": "Uppsala domkyrka",
          "coordinates": {
            "_latitude": 59.854,
            "_longitude": 17.6261
          }
        },
        "Uppsala moské": {
          "name": "Uppsala moské",
          "coordinates": {
            "_latitude": 59.8581,
            "_longitude": 17.6336
          }
        }
      }
    }
  }
}

这是我到目前为止所到达的命令:

[.features[] | {name: .properties.name, coordinates: {_latitude: .geometry.coordinates[0], _longitude: .geometry.coordinates[1]}}]

要产生此结果,这是不正确的:

[
  {
    "name": "Uppsala domkyrka",
    "coordinates": {
      "_latitude": 17.6336159,
      "_longitude": 59.8581466
    }
  },
  {
    "name": "Uppsala moské",
    "coordinates": {
      "_latitude": 17.6382165,
      "_longitude": 59.874003
    }
  }
]

我还没有设法获得name的值作为对象的键。

有什么想法吗?我已经读了几个小时,然后把头发拉出来。.

2 个答案:

答案 0 :(得分:1)

由于您要对三个最上面的键进行硬编码,因此解决方案的键为add

{
  "cities": {
    "uppsala": {
      "locations":
        [.features[]
         | {name: .properties.name,
            coordinates:
              {_latitude: .geometry.coordinates[0],
               _longitude: .geometry.coordinates[1]
              }
            }
         | {(.name): .}
        ] | add
    }
  }
}

如果您不想name的冗余,可以将{(.name): .}替换为:

{(.name): del(.name)}

更紧凑的变体

关键的add在上述内容中有所遗漏,因此您可能要考虑这种等效的选择:

[.features[]
 | {name: .properties.name,
    coordinates:
      { _latitude: .geometry.coordinates[0],
        _longitude: .geometry.coordinates[1]
      }
   } | {(.name): .} ]
| add as $v
| ({} | .cities.uppsala.locations = $v)

答案 1 :(得分:0)

或者这可以使用基于步行路径的Unix实用程序 jtc 解决。

如果每个功能的标签name都是唯一的,则解决方案将如下所示:

bash $ <<<'{"cities":{"uppsala":{"locations":0}}}' jtc -w'<locations>l' -mu src.json -u'<name>l:<N>v[-2]<coordinates>l[0]<LN>v[-1][1]' -T'{"{N}":{"name":"{N}","coordinates":{"_latitude":{},"_longtitude":{LN}}}}'
{
   "cities": {
      "uppsala": {
         "locations": {
            "Uppsala domkyrka": {
               "coordinates": {
                  "_latitude": 59.8581466,
                  "_longtitude": 17.6336159
               },
               "name": "Uppsala domkyrka"
            },
            "Uppsala moské": {
               "coordinates": {
                  "_latitude": 59.874003,
                  "_longtitude": 17.6382165
               },
               "name": "Uppsala moské"
            }
         }
      }
   }
}
bash $ 

源json的遍历路径(在第二个-u选项中很简单):

  • 递归查找并按标签name<name>l:<N>)记住每条记录
  • 然后从发现的记录中进行2级升级,并通过标签(coordinates)递归[-2]<coordinates>l
  • 然后选择并存储(在各自的命名空间中)经度,然后选择纬度([0]<LN>v[-1][1])-注意,不需要存储最后选择的JSON元素,因为在模板中,最后选择的元素可以通过{进行插值{1}}表示法

PS>披露:我是{}-用于JSON操作的shell cli工具的创建者