Как разбить строковое значение в json и преобразовать во вложенные объекты, используя jq? - PullRequest
0 голосов
/ 04 октября 2018

Я пытаюсь использовать jq, чтобы преобразовать что-то вроде этого:

[
  {
    "type": "Feature",
    "properties": {
      "osm_id": "172544",
      "highway": "crossing",
      "other_tags": "\"crossing\"=>\"uncontrolled\",\"tactile_paving\"=>\"yes\""
    },
    "geometry": {
      "type": "Point",
      "coordinates": [
        13.3432342,
        52.5666157
      ]
    }
  }
]

в это:

[
  {
    "type": "Feature",
    "properties": {
      "osm_id": "172544",
      "highway": "crossing",
      "other_tags": {
        "crossing": "uncontrolled",
        "tactile_paving": "yes"
      }
    },
    "geometry": {
      "type": "Point",
      "coordinates": [
        13.3432342,
        52.5666157
      ]
    }
  }
]

прямо сейчас, это мой прогресс:

jq 'map(try(.properties.other_tags |= split(",") // .)) | map(try(.properties.other_tags[] |= split("=>") // .)) | map(try(.properties.other_tags[] |= { (.[0]) : .[1] } // .))' example.json

но вывод «other_tags» выглядит следующим образом:

  "other_tags": [
    {
      "\"crossing\"": "\"uncontrolled\""
    },
    {
      "\"tactile_paving\"": "\"yes\""
    }
  ]

Я почти уверен, что это не так эффективно, как могло бы быть.

Он используется для преобразования экспорта osm,которые довольно велики

Есть ли более элегантная / короткая инструкция jq, которую я могу использовать, также дающая желаемый результат, как указано выше?

Ответы [ 3 ]

0 голосов
/ 04 октября 2018

Вы также можете использовать это:

<file jq '[.[] | try(.properties.other_tags |= ("{" + gsub("=>"; ":") + "}" | fromjson))//.]'

Это добавляет фигурные скобки { и } к требуемой строке и заменит => на :.Затем строка преобразуется как объект JSON с помощью команды fromjson.

Команда не изменяет данные JSON, если .properties.other_tags не найден.

0 голосов
/ 04 октября 2018

Вот решение, которое предполагает, что входные данные могут быть проанализированы в разделенных запятыми сегментах, соответствующих следующему регулярному выражению (выраженному в JSON):

"\"(?<key>[^\"]+)\"=>\"(?<value>[^\"]+)\""

# emit a stream
def unwrap:
  . as $s
  | if length==0 then empty
    else match( "\"(?<key>[^\"]+)\"=>\"(?<value>[^\"]+)\",?" )
    | (.captures|map({(.name): .string})|add), 
      ( $s[.length:]|unwrap)
    end
;

 map( .properties.other_tags |= ([unwrap]|from_entries) )

ThisПодход имеет (потенциальное) преимущество, заключающееся в том, что он допускает запятые и вхождения «=>» в ключах и значениях.Конечно, реализация может быть обоснована (например, используя try, как вы это сделали), но я оставил ее простой, чтобы вы могли легко вносить изменения, чтобы удовлетворить ваши более подробные требования.

0 голосов
/ 04 октября 2018

нашел удовлетворительное решение, возясь с jqplay :

jq '.features
  | map(try(.properties.other_tags |=
            (split("\",\"")
             | join("\"##strsplit##\"")
             | split("##strsplit##")
             | .[] |= split("=>") 
             | .[] |= {(.[0][1:-1]): (.[1][1:-1])}
             | add)) // .)'

edit: изменил индекс массива, благодаря пику за ваш комментарий

edit2: запятаятерпимый и включает узлы без 'other_tags'

...