แยก JSON โดยใช้ Python หรือไม่


18

ฉันมีไฟล์ JSON members.jsonดังต่อไปนี้

{
   "took": 670,
   "timed_out": false,
   "_shards": {
      "total": 8,
      "successful": 8,
      "failed": 0
   },
   "hits": {
      "total": 74,
      "max_score": 1,
      "hits": [
         {
            "_index": "2000_270_0",
            "_type": "Medical",
            "_id": "02:17447847049147026174478:174159",
            "_score": 1,
            "_source": {
               "memberId": "0x7b93910446f91928e23e1043dfdf5bcf",
               "memberFirstName": "Uri",
               "memberMiddleName": "Prayag",
               "memberLastName": "Dubofsky"
            }
         }, 
         {
            "_index": "2000_270_0",
            "_type": "Medical",
            "_id": "02:17447847049147026174478:174159",
            "_score": 1,
            "_source": {
               "memberId": "0x7b93910446f91928e23e1043dfdf5bcG",
               "memberFirstName": "Uri",
               "memberMiddleName": "Prayag",
               "memberLastName": "Dubofsky"
            }
         }
      ]
   }
}

ฉันต้องการที่จะแยกโดยใช้สคริปต์ได้รับเพียงรายชื่อของสนามbashmemberId

ผลลัพธ์ที่คาดหวังคือ:

memberIds
----------- 
0x7b93910446f91928e23e1043dfdf5bcf
0x7b93910446f91928e23e1043dfdf5bcG

ฉันพยายามเพิ่ม bash + python code ต่อไปนี้.bashrc:

function getJsonVal() {
   if [ \( $# -ne 1 \) -o \( -t 0 \) ]; then
       echo "Usage: getJsonVal 'key' < /tmp/file";
       echo "   -- or -- ";
       echo " cat /tmp/input | getJsonVal 'key'";
       return;
   fi;
   cat | python -c 'import json,sys;obj=json.load(sys.stdin);print obj["'$1'"]';
}

แล้วเรียกว่า:

$ cat members.json | getJsonVal "memberId"

แต่มันจะพ่น:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
KeyError: 'memberId'

การอ้างอิง

/programming//a/21595107/432903


2
ทำไมคุณต้องทำสิ่งนี้ด้วยการทุบตี? คุณกำลังใช้งูหลามอย่างชัดเจนที่นี่ดังนั้นทำไมไม่เพียงสร้างสคริปต์งูหลามที่ทำงานได้? คุณอาจไม่ได้รับคำตอบที่แท้จริงเกี่ยวกับวิธีการใช้ bash เพราะเมื่อคุณต้องทำสิ่งนั้นมากคุณใช้ภาษาอื่น
DavidG

ฉันเปลี่ยนชื่อของคุณจาก"using bash script"เป็น"using python"ตั้งแต่pythonและไม่ใช่bashสิ่งที่คุณใช้ในการแยกวิเคราะห์ json เช่นข้อผิดพลาดนั้นเป็นข้อผิดพลาดของ python ไม่ใช่ข้อผิดพลาด bash
goldilocks

@goldilocks เพียงเพราะความพยายามของเขาใช้pythonไม่ได้หมายความว่าเป้าหมายของเขาคือการใช้python
jordanm

@DavidG เห็นคำตอบของฉัน มันไม่ใช่เปลือกที่บริสุทธิ์เป็นคำสั่งจากภายนอก แต่มันรวมเข้ากับเชลล์สคริปต์ได้ค่อนข้างดี
จอร์แดน

ฉันขอแนะนำให้คุณลบฟิลด์ที่ไม่เกี่ยวข้องส่วนใหญ่ใน json ได้ไหม การมีองค์ประกอบ 2-3 รายการใน _source เพื่อรับส่วนสำคัญของสิ่งที่คุณพยายามจะทำ ส่วนที่เหลือเพียงกวนใจ
Anthon

คำตอบ:


25

ถ้าคุณจะใช้:

 $ cat members.json | \
     python -c 'import json,sys;obj=json.load(sys.stdin);print obj;'

คุณสามารถตรวจสอบโครงสร้างของ dictonary ที่ซ้อนกันobjและดูว่าบรรทัดต้นฉบับของคุณควรอ่าน:

$ cat members.json | \
    python -c 'import json,sys;obj=json.load(sys.stdin);print obj["hits"]["hits"][0]["_source"]["'$1'"]';

ไปยังองค์ประกอบ "memberId" วิธีนี้คุณสามารถทำให้ Python เป็นแบบออนไลน์ได้

หากมีหลายองค์ประกอบในองค์ประกอบ "จำนวนที่ซ้อนกัน" คุณสามารถทำสิ่งต่อไปนี้:

$ cat members.json | \
python -c '
import json, sys
obj=json.load(sys.stdin)
for y in [x["_source"]["'$1'"] for x in obj["hits"]["hits"]]:
    print y
'

โซลูชันของ Chris Down ดีกว่าสำหรับการค้นหาคีย์เดี่ยว (ไม่ซ้ำกัน) ในทุกระดับ

ด้วยตัวอย่างที่สองของฉันที่พิมพ์ค่าหลายค่าคุณกำลังตีขีด จำกัด ของสิ่งที่คุณควรลองด้วยสายการบินเดียว ณ จุดนั้นฉันเห็นเหตุผลเล็กน้อยว่าทำไมการประมวลผลครึ่งหนึ่งในการทุบตีและย้ายไปยังโซลูชัน Python ที่สมบูรณ์ .


8

วิธีการที่จะทำเช่นนี้ในทุบตีอีกประการหนึ่งคือการใช้jshon นี่คือวิธีแก้ไขปัญหาของคุณโดยใช้jshon:

$ jshon -e hits -e hits -a -e _source -e memberId -u < foo.json
0x7b93910446f91928e23e1043dfdf5bcf
0x7b93910446f91928e23e1043dfdf5bcG

-eตัวเลือกดึงค่าจาก JSON -aiterates มากกว่าอาร์เรย์และ-uถอดรหัสสตริงสุดท้าย


ให้ฉันติดตั้ง jshon
prayagupd

6

คีย์ของคุณค่อนข้างชัดเจนว่าไม่อยู่ที่รากของวัตถุ ลองสิ่งนี้:

json_key() {
    python -c '
import json
import sys

data = json.load(sys.stdin)

for key in sys.argv[1:]:
    try:
        data = data[key]
    except TypeError:  # This is a list index
        data = data[int(key)]

print(data)' "$@"
}

สิ่งนี้มีประโยชน์ไม่ใช่เพียงแค่การแทรกไวยากรณ์ลงใน Python ซึ่งอาจทำให้เกิดการแตกหัก (หรือแย่กว่านั้นคือการใช้รหัสโดยอำเภอใจ)

จากนั้นคุณสามารถเรียกสิ่งนี้ได้:

json_key hits hits 0 _source memberId < members.json

1
หมายเหตุ: สิ่งนี้จะไม่วนซ้ำแต่ละรายการใน "จำนวนครั้ง" หากคุณต้องการคุณควรเขียนรหัส Python เฉพาะสำหรับอินสแตนซ์นั้น
Chris Down

แต่มันจะแสดงเพียงหนึ่งรหัสสมาชิกเท่านั้น
prayagupd

4

อีกทางเลือกหนึ่งคือjq :

$ cat members.json | jq -r '.hits|.hits|.[]|._source|.memberId'
0x7b93910446f91928e23e1043dfdf5bcf
0x7b93910446f91928e23e1043dfdf5bcG

2

ลองสิ่งนี้:

$ cat json.txt | python -c 'import sys; import simplejson as json; \
print "\n".join( [i["_source"]["memberId"] for i in json.loads( sys.stdin.read() )["hits"]["hits"]] )'


หากคุณมีpretty printedjson อยู่แล้วทำไมคุณgrepไม่ลองล่ะ

$ cat json.txt | grep memberId
               "memberId": "0x7b93910446f91928e23e1043dfdf5bcf",
               "memberId": "0x7b93910446f91928e23e1043dfdf5bcG",

คุณสามารถได้รับรูปแบบที่พิมพ์สวยด้วย simplejson หลามgrepมัน

# cat json_raw.txt
{"hits": {"hits": [{"_score": 1, "_type": "Medical", "_id": "02:17447847049147026174478:174159", "_source": {"memberLastName": "Dubofsky", "memberMiddleName": "Prayag", "memberId": "0x7b93910446f91928e23e1043dfdf5bcf", "memberFirstName": "Uri"}, "_index": "2000_270_0"}, {"_score": 1, "_type": "Medical", "_id": "02:17447847049147026174478:174159", "_source": {"memberLastName": "Dubofsky", "memberMiddleName": "Prayag", "memberId": "0x7b93910446f91928e23e1043dfdf5bcG", "memberFirstName": "Uri"}, "_index": "2000_270_0"}], "total": 74, "max_score": 1}, "_shards": {"successful": 8, "failed": 0, "total": 8}, "took": 670, "timed_out": false}

ใช้การถ่ายโอนข้อมูล:

# cat json_raw.txt | python -c 'import sys; import simplejson as json; \
print json.dumps( json.loads( sys.stdin.read() ), sort_keys=True, indent=4); '

{
    "_shards": {
        "failed": 0,
        "successful": 8,
        "total": 8
    },
    "hits": {
        "hits": [
            {
                "_id": "02:17447847049147026174478:174159",
                "_index": "2000_270_0",
                "_score": 1,
                "_source": {
                    "memberFirstName": "Uri",
                    "memberId": "0x7b93910446f91928e23e1043dfdf5bcf",
                    "memberLastName": "Dubofsky",
                    "memberMiddleName": "Prayag"
                },
                "_type": "Medical"
            },
            {
                "_id": "02:17447847049147026174478:174159",
                "_index": "2000_270_0",
                "_score": 1,
                "_source": {
                    "memberFirstName": "Uri",
                    "memberId": "0x7b93910446f91928e23e1043dfdf5bcG",
                    "memberLastName": "Dubofsky",
                    "memberMiddleName": "Prayag"
                },
                "_type": "Medical"
            }
        ],
        "max_score": 1,
        "total": 74
    },
    "timed_out": false,
    "took": 670
}

หลังจากนั้นเพียง grepส่งผลให้มีรูปแบบ 'memberId'

จะแม่นยำอย่างสมบูรณ์:

#!/bin/bash

filename="$1"
cat $filename | python -c 'import sys; import simplejson as json; \
print json.dumps( json.loads( sys.stdin.read() ), sort_keys=True, indent=4)' | \
grep memberId | awk '{print $2}' | sed -e 's/^"//g' | sed -e 's/",$//g'

การใช้งาน:

$ bash bash.sh json_raw.txt 
0x7b93910446f91928e23e1043dfdf5bcf
0x7b93910446f91928e23e1043dfdf5bcG


0

การใช้deepdiffคุณไม่จำเป็นต้องรู้รหัสที่แน่นอน:

import json
from deepdiff import DeepSearch
DeepSearch(json.load(open("members.json", "r")), 'memberId', verbose_level=2)['matched_paths'].values()

0

นี่เป็นวิธีทุบตี

  1. สร้างไฟล์ find_members.sh
  2. เพิ่มบรรทัดต่อไปนี้ในไฟล์ + บันทึก

    #!/bin/bash
    
    echo -e "\nmemberIds\n---------"
    cat members.json | grep -E 'memberId'|awk '{print$2}' | cut -d '"' -f2
  3. chmod +x find_members.sh

ตอนนี้เรียกใช้:

$ ./find_members.sh

memberIds
----------------
0x7b93910446f91928e23e1043dfdf5bcf
0x7b93910446f91928e23e1043dfdf5bcG
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.