jq: setpaths с регулярным выражением на путях, как обрабатывать пути, которые заканчиваются целым числом, которое выдает ошибку? - PullRequest
1 голос
/ 07 мая 2019

У меня есть следующий объект:

{
  "domainId": "hidden",
  "lastUsed": "Thu Oct 04 2018",
  "lastUsedTimestamp": 1538673002460,
  "users": [
    {
      "userId": "hidden",
      "lastUsedTimestamp": 1538673002460
    },
    {
      "userId": "hidden",
      "lastUsedTimestamp": 1536087726701
    },
    {
      "userId": "hidden",
      "lastUsedTimestamp": 1536086675399
    },
    {
      "userId": "hidden",
      "lastUsedTimestamp": 1536182646984
    }
  ]
}

Я хочу преобразовать все lastUsedTimestamp значения в дату. Это работает с:

reduce (paths | select(.[-1] == "lastUsedTimestamp")) as $p 
  (.;setpath($p; getpath($p) / 1000 | todate))

Но что, если бы у меня были другие метки времени, такие как createdTimestamp или startTimestamp в других местах объекта? Например:

{
  "domainId": "hidden",
  "lastUsed": "Thu Oct 04 2018",
  "lastUsedTimestamp": 1538673002460,
  "users": [
    {
      "userId": "hidden",
      "lastUsedTimestamp": 1538673002460
    },
    {
      "userId": "hidden",
      "lastUsedTimestamp": 1536087726701
    },
    {
      "userId": "hidden",
      "lastUsedTimestamp": 1536086675399,
      "createdTimestamp": 1536086675399
    },
    {
      "userId": "hidden",
      "lastUsedTimestamp": 1536182646984,
      "startTimestamp": 1536182646984
    }
  ]
}

Я пытался

reduce (paths | select(.[-1] | endswith("Timestamp")) as $p 
  (.;setpath($p; getpath($p) / 1000 | todate))

или эквивалент с test, но пути, заканчивающиеся целым числом, приводят к сбою.

Как я могу обойти это?

Ответы [ 2 ]

2 голосов
/ 07 мая 2019

Для подавления ошибок используйте оператор ... ?, который является сокращением для try ....Например:

reduce (paths|select(.[-1]|endswith("Timestamp")</code><b>?</b><code>)) as $p
(.; setpath($p; getpath($p)/1000|todate))
1 голос
/ 07 мая 2019

Для такого типа проблем часто удобно использовать walk/1:

def timestamps:
  with_entries(if .key | endswith("Timestamp")
               then .value |= (./1000 | todate) else . end);

walk( if type == "object" then timestamps else . end )

как однострочник

Если вы хотите однострочник:

walk( if type == "object" then with_entries(if .key | endswith("Timestamp") then .value |= (./1000 | todate) else . end) else . end)

Если ваш jq позволяет опустить else ., это становится немного более удобочитаемым:

walk(if type == "object" then with_entries(if .key | endswith("Timestamp") then .value |= (./1000 | todate) end) end)
...