স্বেচ্ছাসেবী JSON কে সিএসভিতে জিকিউ ব্যবহার করে কীভাবে রূপান্তর করবেন?


108

জেকিউ ব্যবহার করে , কীভাবে নির্বিচারে জেএসওএন এনকোডিং করে অগভীর অবজেক্টের অ্যারে সিএসভিতে রূপান্তর করা যায়?

এই সাইটটিতে প্রচুর প্রশ্নোত্তর রয়েছে যা নির্দিষ্ট ডেটা মডেলগুলির ক্ষেত্রগুলিকে হার্ড-কোড করে থাকে তবে এই প্রশ্নের উত্তরগুলি যে কোনও জেএসএনকে দেওয়া উচিত, কেবলমাত্র এটি সীমাবদ্ধ বৈশিষ্ট্যযুক্ত বস্তুর অ্যারে (কোনও গভীর / জটিল / সাব-অবজেক্টস যেমন এটিকে চাটুকার করা অন্য প্রশ্ন) ফলাফলটিতে মাঠের নাম দেওয়ার সাথে একটি শিরোনাম সারি থাকা উচিত। প্রথম বস্তুর ক্ষেত্র ক্রম সংরক্ষণ করে এমন উত্তরগুলিতে অগ্রাধিকার দেওয়া হবে, তবে এটির প্রয়োজন নেই। ফলাফলগুলি সমস্ত কোষগুলিকে ডাবল-কোট দিয়ে আবদ্ধ করতে পারে বা কেবল উক্ত আবশ্যকতাগুলিকে আবদ্ধ করতে পারে (যেমন 'এ, বি'))

উদাহরণ

  1. ইনপুট:

    [
        {"code": "NSW", "name": "New South Wales", "level":"state", "country": "AU"},
        {"code": "AB", "name": "Alberta", "level":"province", "country": "CA"},
        {"code": "ABD", "name": "Aberdeenshire", "level":"council area", "country": "GB"},
        {"code": "AK", "name": "Alaska", "level":"state", "country": "US"}
    ]
    

    সম্ভাব্য আউটপুট:

    code,name,level,country
    NSW,New South Wales,state,AU
    AB,Alberta,province,CA
    ABD,Aberdeenshire,council area,GB
    AK,Alaska,state,US
    

    সম্ভাব্য আউটপুট:

    "code","name","level","country"
    "NSW","New South Wales","state","AU"
    "AB","Alberta","province","CA"
    "ABD","Aberdeenshire","council area","GB"
    "AK","Alaska","state","US"
    
  2. ইনপুট:

    [
        {"name": "bang", "value": "!", "level": 0},
        {"name": "letters", "value": "a,b,c", "level": 0},
        {"name": "letters", "value": "x,y,z", "level": 1},
        {"name": "bang", "value": "\"!\"", "level": 1}
    ]
    

    সম্ভাব্য আউটপুট:

    name,value,level
    bang,!,0
    letters,"a,b,c",0
    letters,"x,y,z",1
    bang,"""!""",0
    

    সম্ভাব্য আউটপুট:

    "name","value","level"
    "bang","!","0"
    "letters","a,b,c","0"
    "letters","x,y,z","1"
    "bang","""!""","1"
    

তিন-প্লাস বছর পরে ... একটি জেনেরিক json2csvহয় stackoverflow.com/questions/57242240/...
শিখর

উত্তর:


163

প্রথমে, আপনার অবজেক্ট অ্যারে ইনপুটটিতে সমস্ত পৃথক অবজেক্ট বৈশিষ্ট্যের নাম যুক্ত একটি অ্যারে পান। এগুলি আপনার সিএসভির কলাম হবে:

(map(keys) | add | unique) as $cols

তারপরে, অবজেক্ট অ্যারে ইনপুটটিতে প্রতিটি বস্তুর জন্য, বস্তুর সংশ্লিষ্ট বৈশিষ্ট্যগুলিতে প্রাপ্ত কলামের নামগুলি ম্যাপ করুন। এগুলি আপনার সিএসভির সারি হবে।

map(. as $row | $cols | map($row[.])) as $rows

শেষ অবধি, CSV এর শিরোনাম হিসাবে সারিগুলির আগে কলামের নামগুলি রাখুন এবং ফলস্বরূপ সারি স্ট্রিমটি @csvফিল্টারটিতে দিন।

$cols, $rows[] | @csv

সব একসঙ্গে এখন. -rকাঁচা স্ট্রিং হিসাবে ফলাফল পেতে পতাকা ব্যবহার করতে ভুলবেন না:

jq -r '(map(keys) | add | unique) as $cols | map(. as $row | $cols | map($row[.])) as $rows | $cols, $rows[] | @csv'

6
এটি দুর্দান্ত যে আপনার সমাধানটি কেবল প্রথমটির পরিবর্তে সমস্ত সারি থেকে সমস্ত সম্পত্তির নাম ক্যাপচার করে। যদিও আমি খুব বিস্তৃত নথিগুলির জন্য এর পারফরম্যান্সের প্রভাবগুলি কী তা অবাক করি। পিএস যদি আপনি চান তবে আপনি $rowsকেবলমাত্র ইনলাইনিং করে ভেরিয়েবল অ্যাসাইনমেন্ট থেকে মুক্তি পেতে পারেন :(map(keys) | add | unique) as $cols | $cols, map(. as $row | $cols | map($row[.]))[] | @csv
জর্দান

9
ধন্যবাদ, জর্ডান! আমি সচেতন যে $rowsকোনও ভেরিয়েবলের জন্য নিযুক্ত করতে হবে না; আমি কেবল ভেবেছিলাম এটিকে কোনও ভেরিয়েবলের সাথে নিযুক্ত করা ব্যাখ্যাটি আরও ভাল করেছে।

4
সারি মান রূপান্তর বিবেচনা করুন নেস্টেড অ্যারে বা মানচিত্রের ক্ষেত্রে স্ট্রিং রয়েছে।
টিজেআর

ভাল পরামর্শ, @ টিজেআর। সম্ভবত যদি নেস্টেড স্ট্রাকচারগুলি থাকে, জেউকে তাদের মধ্যে পুনরাবৃত্তি করা উচিত এবং তাদের মানগুলিকে কলামেও তৈরি করা উচিত
মিঃ ল্যান্স ই স্লোয়ান

JSON কোনও ফাইলে থাকলে এবং আপনি কিছু নির্দিষ্ট ডেটা সিএসভিতে ফিল্টার করতে চাইলে কীভাবে এই পার্থক্য হবে?
মিস্টার পজিটিভ

92

চর্মসার

jq -r '(.[0] | keys_unsorted) as $keys | $keys, map([.[ $keys[] ]])[] | @csv'

বা:

jq -r '(.[0] | keys_unsorted) as $keys | ([$keys] + map([.[ $keys[] ]])) [] | @csv'

বিস্তারিত

পাশে

বিশদটি বর্ণনা করা জটিল কারণ জেকিউ স্ট্রিম-ওরিয়েন্টড, এর অর্থ এটি কোনও একক মানের পরিবর্তে জেএসওএন ডেটার ক্রমিকায় কাজ করে। ইনপুট জেএসএন স্ট্রিমটি কিছু অভ্যন্তরীণ প্রকারে রূপান্তরিত হয় যা ফিল্টারগুলির মধ্য দিয়ে যায় এবং তারপরে প্রোগ্রামের শেষে একটি আউটপুট স্ট্রিমে এনকোড হয়। অভ্যন্তরীণ প্রকারটি JSON দ্বারা মডেলিং হয় না এবং নামযুক্ত ধরণের হিসাবে উপস্থিত হয় না। এটি একটি বেয়ার ইনডেক্স ( .[]) বা কমা অপারেটরের আউটপুট পরীক্ষা করে খুব সহজেই প্রদর্শিত হয় (এটি সরাসরি পরীক্ষা করা কোনও ডিবাগারের সাহায্যে করা যেতে পারে, তবে এটি জেএসএন-এর পিছনে ধারণাগত ডেটা ধরণের পরিবর্তে জেউ-র অভ্যন্তরীণ ডেটা ধরণের ক্ষেত্রে হতে পারে) ।

$ jq -c '। []' <<< '["ক", "খ"]'
"ক"
"খ"
$ jq -cn '"এ", "বি"'
"ক"
"খ"

দ্রষ্টব্য যে আউটপুট কোনও অ্যারে নয় (যা হবে ["a", "b"])। কমপ্যাক্ট আউটপুট ( -cবিকল্প) দেখায় যে প্রতিটি অ্যারে উপাদান (বা ,ফিল্টারের সাথে যুক্তি ) আউটপুটে একটি পৃথক বস্তুতে পরিণত হয় (প্রত্যেকে পৃথক লাইনে থাকে)।

একটি স্ট্রীম একটি মত হল তাদেরকে JSON-SeQ , বরং তুলনায় নতুন লাইন ব্যবহার আরএস যখন এনকোড একটি আউটপুট বিভাজক হিসাবে। ফলস্বরূপ, এই অভ্যন্তরীণ ধরণটি জেনেরিক শব্দটি "উত্তর" এর সাথে উত্তরটিতে এনকোডড ইনপুট এবং আউটপুট জন্য "স্ট্রিম" দিয়ে সংরক্ষণ করা হয়।

ফিল্টার নির্মাণ

প্রথম অবজেক্টের কীগুলি এর সাথে বের করা যেতে পারে:

.[0] | keys_unsorted

কীগুলি সাধারণত তাদের মূল ক্রমে রাখা হবে তবে সঠিক ক্রম সংরক্ষণের নিশ্চয়তা নেই। ফলস্বরূপ, একই ক্রমে মানগুলি পেতে সেগুলিকে সূচকগুলি ব্যবহার করতে হবে to যদি কিছু বস্তুর আলাদা কী অর্ডার থাকে তবে এটি ভুল কলামগুলিতে থাকা মানগুলিও প্রতিরোধ করবে।

উভয়কে প্রথম সারির হিসাবে কীগুলি আউটপুট দেওয়ার জন্য এবং এগুলি সূচীকরণের জন্য উপলব্ধ করার জন্য, তারা একটি ভেরিয়েবলে সংরক্ষণ করা হয়। পাইপলাইনের পরবর্তী পর্যায়ে তারপরে এই পরিবর্তনশীলটিকে উল্লেখ করে এবং আউটপুট প্রবাহে শিরোনামটি প্রিপেন্ড করতে কমা অপারেটর ব্যবহার করে।

(.[0] | keys_unsorted) as $keys | $keys, ...

কমা পরে অভিব্যক্তি একটু জড়িত। কোনও বস্তুর সূচক অপারেটর স্ট্রিংগুলির ক্রম নিতে পারে (উদাহরণস্বরূপ "name", "value"), সেই স্ট্রিংগুলির জন্য সম্পত্তি মানগুলির ক্রম ফিরিয়ে আনতে পারে। $keysএকটি অ্যারে, ক্রম নয়, সুতরাং []এটি একটি অনুক্রমে রূপান্তর করতে প্রয়োগ করা হয়,

$keys[]

যা পরে পাস করা যেতে পারে .[]

.[ $keys[] ]

এটিও একটি সিক্যুয়েন্স তৈরি করে, সুতরাং অ্যারে কনস্ট্রাক্টর এটি অ্যারে রূপান্তর করতে ব্যবহৃত হয়।

[.[ $keys[] ]]

এই অভিব্যক্তিটি একটি একক বস্তুর জন্য প্রয়োগ করতে হবে। map()এটি বাইরের অ্যারেতে সমস্ত বস্তুর জন্য প্রয়োগ করতে ব্যবহৃত হয়:

map([.[ $keys[] ]])

শেষ পর্যন্ত এই পর্যায়ে, এটি একটি অনুক্রমে রূপান্তরিত হয় যাতে প্রতিটি আইটেম আউটপুটে একটি পৃথক সারিতে পরিণত হয়।

map([.[ $keys[] ]])[]

সিক্যুয়েন্সটি কেন mapএটির বাইরে আনব্যান্ডল করার জন্য কেবল বিন্যাসে অ্যারেতে বান্ডিল করবেন ? mapএকটি অ্যারে উত্পাদন করে; .[ $keys[] ]একটি ক্রম উত্পাদন করে। mapসিকোয়েন্স থেকে প্রয়োগ করা হলে .[ $keys[] ]মানগুলির ক্রমগুলির একটি অ্যারে তৈরি হবে, তবে যেহেতু অনুক্রমগুলি কোনও JSON প্রকার নয়, সুতরাং পরিবর্তে আপনি সমস্ত মান সমেত একটি সমতল অ্যারে পাবেন।

["NSW","AU","state","New South Wales","AB","CA","province","Alberta","ABD","GB","council area","Aberdeenshire","AK","US","state","Alaska"]

প্রতিটি বস্তুর মানগুলি পৃথক করে রাখা দরকার, যাতে তারা চূড়ান্ত আউটপুটে পৃথক সারি হয়ে যায়।

অবশেষে, সিকোয়েন্সটি @csvফর্ম্যাটারের মাধ্যমে পাস করা হয় ।

বিকল্প

আইটেমগুলি প্রথম চেয়ে বরং দেরিতে পৃথক করা যায়। সিকোয়েন্স পেতে কমা অপারেটরটি ব্যবহার করার পরিবর্তে (ডান অপারেণ্ড হিসাবে একটি অনুক্রম পাস করা) শিরোনাম সিকোয়েন্স ( $keys) একটি অ্যারেতে আবৃত হতে পারে এবং +মানগুলির অ্যারে সংযোজন করতে ব্যবহৃত হয়। এখনও পাস হওয়ার আগে একটা ক্রম রূপান্তরিত করার জন্য দরকার @csv


4
আপনি কি প্রথম আদেশ থেকে কী ক্রম সংরক্ষণের keys_unsortedপরিবর্তে ব্যবহার করতে পারেন keys?
জর্ডান চলছে

4
@ আউটিস - স্ট্রিমগুলির পূর্বনির্ধারণ কিছুটা ভুল c সাধারণ সত্যটি হল যে জেকিউ ফিল্টারগুলি স্ট্রিম-ওরিয়েন্টেড। এটি হ'ল যে কোনও ফিল্টার JSON সত্তার একটি স্ট্রিম গ্রহণ করতে পারে এবং কিছু ফিল্টার মানগুলির স্ট্রিম তৈরি করতে পারে। কোনও স্ট্রিমের আইটেমগুলির মধ্যে কোনও "নতুন লাইন" বা অন্য কোনও বিভাজক নেই - এটি কেবল তখন প্রিন্ট করা হয় যে কোনও বিভাজককে পরিচয় করানো হয়। নিজের জন্য দেখুন, চেষ্টা করুন: jq -n -c 'হ্রাস ("a", "বি") হিসাবে $ s ("";। + $ S)'
শিখর

এটি যখন লেখা হয়েছিল এবং এখন এটি ভুল রেন্ডার করার মধ্যে কিছু ঘটেছিল? সমস্যাটি মানচিত্রে মনে হচ্ছে, যা খেলনা উদাহরণেও ভেঙে যায়: জেউ -১.৫ এ $ echo '{"a":1,"b":2,"c":3}' |jq -r '(. | keys_unsorted) as $keys| $keys, map( [.[ $keys[] ] ])[] | @csv'আউটপুট "a","b","c" jq: error (at <stdin>:1): Cannot index number with string "a"দেয়।
উইয়াট

4
@ ওয়াট: আপনার ডেটা এবং উদাহরণ ইনপুটটি ঘনিষ্ঠভাবে দেখুন। প্রশ্নটি কোনও একক অবজেক্ট নয়, অবজেক্টের অ্যারে সম্পর্কে। ব্যবহার করে দেখুন [{"a":1,"b":2,"c":3}]
আউটিস

এই সমাধানের বিশদটির মাধ্যমে কাজ করা আমাকে জেকিউ সম্পর্কে প্রচুর শিখিয়েছে! বিশদের সাথে লড়াই করা অন্য যে কোনও ব্যক্তির জন্য, "jq -cr" (। [[0] | কী_অনসোর্টড) এর সাথে $ অ্যারে_ফ_কিজস $ অ্যারে_ফ_কিজ, (। [[]] [[[Ray অ্যারে_ফ_কিজ []]]] হিসাবে খেলতে সহায়ক হতে পারে | '', যেহেতু মানচিত্রের ফিল্টারটি এভাবে প্রয়োগ করা হয়। এবং মনে রাখবেন যে "(foo) $ বার" ভেরিয়েবল অ্যাসাইনমেন্টটি আসলে প্রত্যেকটির জন্য কাজ করে যা (foo) এক্সপ্রেশনটির সমস্ত আইটেমের উপরে পুনরাবৃত্তি করে (এই ক্ষেত্রে কোনও সমস্যা নয়, যেহেতু আমরা কীগুলি টানছি একক আইটেম)।
রায় উড

6

আমি একটি ফাংশন তৈরি করেছি যা শিরোনামগুলির সাথে সিএসভিতে অবজেক্ট বা অ্যারেগুলির একটি অ্যারে আউটপুট করে। কলামগুলি শিরোনামগুলির ক্রমে থাকবে।

def to_csv($headers):
    def _object_to_csv:
        ($headers | @csv),
        (.[] | [.[$headers[]]] | @csv);
    def _array_to_csv:
        ($headers | @csv),
        (.[][:$headers|length] | @csv);
    if .[0]|type == "object"
        then _object_to_csv
        else _array_to_csv
    end;

সুতরাং আপনি এটি এর মতো ব্যবহার করতে পারেন:

to_csv([ "code", "name", "level", "country" ])

6

নিম্নলিখিত ফিল্টারটি সামান্য আলাদা যে এটি প্রতিটি মানকে স্ট্রিতে রূপান্তরিত করে তা নিশ্চিত করবে। (jq 1.5+)

# For an array of many objects
jq -f filter.jq [file]

# For many objects (not within array)
jq -s -f filter.jq [file]

ছাঁকনি: filter.jq

def tocsv:
    (map(keys)
        |add
        |unique
        |sort
    ) as $cols
    |map(. as $row
        |$cols
        |map($row[.]|tostring)
    ) as $rows
    |$cols,$rows[]
    | @csv;

tocsv

4
এটি সাধারণ JSON এর পক্ষে ভাল কাজ করে তবে নীচের বৈশিষ্ট্যগুলি যা JSON এর সাথে অনেকগুলি স্তরে যায় সে সম্পর্কে কী?
আমির

এটি অবশ্যই কীগুলি বাছাই করে। এছাড়াও আউটপুট uniqueযেকোন উপায়ে বাছাই করা হয়, তাই unique|sortসহজ করা যেতে পারে unique
শিখর

4
@ টিজেআর এই ফিল্টারটি ব্যবহার করার সময় -rঅপশনটি ব্যবহার করে কাঁচা আউটপুট চালু করা বাধ্যতামূলক । অন্যথায় সমস্ত উদ্ধৃতি "অতিরিক্ত পলায়ন হয়ে যায় যা বৈধ সিএসভি নয়।
টুশ

আমির: নেস্টেড বৈশিষ্ট্যগুলি সিএসভিতে মানচিত্র করে না।
ক্রিশমোরিস

2

সান্টিয়াগো প্রোগ্রামের এই রূপটিও নিরাপদ তবে এটি নিশ্চিত করে যে প্রথম অবজেক্টের মূল নামগুলি প্রথম কলাম শিরোনাম হিসাবে ব্যবহৃত হবে that বস্তুটিতে যেভাবে প্রদর্শিত হবে:

def tocsv:
  if length == 0 then empty
  else
    (.[0] | keys_unsorted) as $keys
    | (map(keys) | add | unique) as $allkeys
    | ($keys + ($allkeys - $keys)) as $cols
    | ($cols, (.[] as $row | $cols | map($row[.])))
    | @csv
  end ;

tocsv
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.