MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

Как да конвертирате произволно вложен JSON в CSV с jq – така че да можете да го конвертирате обратно?

Следният tocsv и fromcsv функции предоставят решение на посочения проблем с изключение на едно усложнение по отношение на изискване (6) относно заглавките. По същество това изискване може да бъде изпълнено с помощта на дадените тук функции чрез добавяне на стъпка за транспониране на матрица.

Независимо дали е добавена или не стъпка на транспониране, предимството на възприетия тук подход е, че няма ограничения за JSON ключовете или стойностите. По-специално, те могат да съдържат точки (точки), нови редове и/или NUL знаци.

В примера е даден масив от обекти, но всъщност всеки поток от валидни JSON документи може да се използва като вход към tocsv; благодарение на магията на jq, оригиналният поток ще бъде пресъздаден от fromcsv (в смисъл на равенство на обект по обект).

Разбира се, тъй като няма CSV стандарт, CSV, произведен от tocsv функцията може да не се разбира от всички CSV процесори. По-специално, имайте предвид, че tocsv функцията, дефинирана тук, картографира вградени нови редове в JSON низове или имена на ключове към низа от два знака "\n" (т.е. буквална обратна наклонена черта, последвана от буквата "n"); обратната операция извършва обратния превод, за да отговори на "обръщането" изискване.

(Използването на tail е само за опростяване на представянето; би било нетривиално да модифицирате решението, за да го направите само-jq.)

CSV се генерира при допускането, че всяка стойност може да бъде включена в поле, стига (a) полето да е в кавички и (b) двойните кавички в полето да са удвоени.

Всяко генерично решение, което поддържа "обиколни пътувания", е обвързано да бъде донякъде сложно. Основната причина, поради която представеното тук решение е по-сложно, отколкото може да се очаква, е, че е добавена трета колона, отчасти за да улесни разграничаването между цели числа и низове с цели числа, но главно защото улеснява разграничаването между size-1 и size -2 масива, произведени от jq's--stream опция. Излишно е да казвам, че има други начини, по които тези проблеми могат да бъдат адресирани; броят на обажданията до jq също може да бъде намален.

Решението е представено като тестов скрипт, който проверява двупосочното изискване на показателен тестов случай:

#!/bin/bash

function json {
    cat<<EOF
[
  {
    "a": 1,
    "b": [
      1,
      2,
      "1"
    ],
    "c": "d\",ef",
    "embed\"ed": "quote",
    "null": null,
    "string": "null",
    "control characters": "a\u0000c",
    "newline": "a\nb"
  },
  {
    "x": 1
  }
]
EOF
}

function tocsv {
 jq -ncr --stream '
   (["path", "value", "stringp"],
    (inputs | . + [.[1]|type=="string"]))
   | map( tostring|gsub("\"";"\"\"") | gsub("\n"; "\\n"))
   | "\"\(.[0])\",\"\(.[1])\",\(.[2])" 
'
}

function fromcsv { 
    tail -n +2 | # first duplicate backslashes and deduplicate double-quotes
    jq -rR '"[\(gsub("\\\\";"\\\\") | gsub("\"\"";"\\\"") ) ]"' |
    jq -c '.[2] as $s 
           | .[0] |= fromjson 
           | .[1] |= if $s then . else fromjson end 
           | if $s == null then [.[0]] else .[:-1] end
             # handle newlines
           | map(if type == "string" then gsub("\\\\n";"\n") else . end)' |
    jq -n 'fromstream(inputs)'
}    

# Check the roundtrip:
json | tocsv | fromcsv | jq -s '.[0] == .[1]' - <(json)

Ето CSV, който ще бъде произведен от json | tocsv , с изключение на това, че SO изглежда забранява буквалните NUL, така че го замених с \0 :

"path","value",stringp
"[0,""a""]","1",false
"[0,""b"",0]","1",false
"[0,""b"",1]","2",false
"[0,""b"",2]","1",true
"[0,""b"",2]","false",null
"[0,""c""]","d"",ef",true
"[0,""embed\""ed""]","quote",true
"[0,""null""]","null",false
"[0,""string""]","null",true
"[0,""control characters""]","a\0c",true
"[0,""newline""]","a\nb",true
"[0,""newline""]","false",null
"[1,""x""]","1",false
"[1,""x""]","false",null
"[1]","false",null


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Мога ли да конфигурирам MongoDB да бъде In-Memory?

  2. Поръчка и лимит води до заявка с обратно извикване

  3. Интегриране на ClusterControl със SNMP:Част втора

  4. MongoDB $geoNear тръбопровод за агрегиране (с използване на опция за заявка и използване на $match тръбопроводна операция), даващ различен брой резултати

  5. Javascript API от страна на клиента на Mongodb