파이썬을 사용하여 JSON을 구문 분석 하시겠습니까?


18

members.json아래와 같이 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"
            }
         }
      ]
   }
}

bash스크립트를 사용하여 구문 분석하고 필드 목록 만 가져옵니다 memberId.

예상되는 결과는 다음과 같습니다.

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

다음 bash + python 코드를 추가하려고했습니다 .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에서 이것을해야합니까? 여기서 파이썬을 분명히 사용하고 있으므로 왜 작업을 수행하는 파이썬 스크립트를 작성하지 않습니까? bash를 사용하여 수행하는 방법에 대한 실제 답변을 얻지 못할 수도 있습니다. 왜냐하면 그렇게 많이해야 할 때 다른 언어를 사용하기 때문입니다.
DavidG

귀하의 제목을 "bash 스크립트 사용" 에서 "python 사용"으로 변경했습니다. 왜냐하면 json을 구문 분석하는 데 사용하는 것이 python아니기 때문 bash입니다. 예를 들어, 그 오류는 분명히 파이썬 오류이며 bash 오류는 아닙니다.
goldilocks

@goldilocks 그의 시도가 사용되었다고 python해서 그의 목표가 사용되는 것은 아닙니다.python
jordanm

@DavidG 내 대답을 참조하십시오. 순수한 쉘은 아니지만 외부 명령이지만 쉘 스크립트에 잘 통합됩니다.
jordanm

json에서 관련이없는 필드를 대부분 꺼내는 것이 좋습니다. _source에 2-3 개의 요소가 있으면 수행하려는 작업의 요지를 얻을 수 있습니다. 나머지는 혼란스러워
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"요소에 이런 식으로 파이썬을 하나의 라이너로 유지할 수 있습니다.

중첩 된 "hits"요소에 여러 요소가있는 경우 다음과 같은 작업을 수행 할 수 있습니다.

$ 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의 솔루션은 모든 수준에서 (고유 한) 단일 키를 찾는 데 더 좋습니다.

여러 값을 출력하는 두 번째 예를 통해 하나의 라이너로 시도해야 할 한계에 도달했습니다. .


8

bash에서 이것을 수행하는 또 다른 방법은 jshon을 사용하는 입니다. 다음을 사용하여 문제에 대한 해결책은 다음과 같습니다 jshon.

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

-e옵션은 JSON에서 값을 추출합니다. 은 -a배열을 통해 반복 처리는 -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)' "$@"
}

이것은 단순히 구문을 파이썬에 주입하는 것만이 아니라 파손 (또는 더 나쁜 임의의 코드 실행)을 유발할 수 있다는 이점이 있습니다.

그런 다음 다음과 같이 호출 할 수 있습니다.

json_key hits hits 0 _source memberId < members.json

1
참고 : "hits"의 각 항목을 반복하지는 않습니다. 원하는 경우 해당 인스턴스에 대한 특정 Python 코드를 작성해야합니다.
Chris Down

그러나 하나의 memberId 만 표시합니다.
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 python으로 꽤 인쇄 된 형식을 얻을 수 있습니다 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

bash 솔루션이 있습니다.

  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.