68364
# やりたいこと

JSONファイルにおいて、あるキーに対する値を取得し、値が格納されている別の場所からidを取ってこようとしています。  
具体的には`sample.json`を以下のようにしたいです。

```

    "order": [
        {
            "customer_id": 1,
            "combinations": {
                "bread":{
                "name":"sesami",
                "bread_id":1
                },
    
                "vegitable":{
                 "name":"spinaches",
                 "vegi_id":2
                }
    
                "meat":{
                "name":"peperoni"
                "meat_id":1
               }
            },
    
            "time": "2020-07-06"
    
        }
    ]
    
```

つまり、前半の「bread, vegitables,
meats」の要素で名前が一致するものがあれば、orderのcombinationの各要素にidを追記したいということです。

# 問題

現在、方針としては

  * 「"combinations"」の値を変数に格納して、
  * 「bread, vegitables, meats」の"name"と一致するか全て探索を行い
  * 一致したもののidを別の変数に格納して
  * orderのcombination全体を書き換える

ということを考えています。

しかし、まず「"combinations"」の値を変数に格納と、JSONにおける探索の方法がわからない状態です。

また、今回やりたいことを実現するための方針への意見やより簡単な方法があれば教えていただきたいです。

# 実行中のプログラム

```

    {
        "sandwich": {
            "breads": [
                {
                    "name": "sesami",
                    "bread_id": 1
                },
                {
                    "name": "white",
                    "bread_id": 2
                }
            ],
            "vegitables": [
                {
                    "name": "tomatos",
                    "vegi_id": 1
                },
                {
                    "name": "spinaches",
                    "vegi_id": 2
                }
            ],
            "meats": [
                {
                    "name": "peperoni",
                    "meat_id": 1
                },
                {
                    "name": "beef",
                    "meat_id": 2
                }
            ],
            "order": [
                {
                    "customer_id": 1,
                    "combinations": {
                        "bread_name":"sesami",
                        "vegi_name":"spinaches",
                        "meat_name":"peperoni"
                    },
    
                    "time": "2020-07-06"
    
                }
            ]
        }
    }
    
```

# 試したこと

指定した要素をとってこれるか確認しました。  
trial.py

```

    import json
    
    json_file = open('sample.json', 'r')
    json_object = json.load(json_file)
    
    print(json_object["sandwich"]["order"])
    
```

```

    $ python trial.py
    [{'customer_id': 1, 'combinations': {'bread_name': 'sesami', 'vegi_name': 'spinaches', 'meat_name': 'peperoni'}, 'time': '2020-07-06'}]
    
```

ただし、`print(json_object["sandwich"]["order"]["combinations"])`と書き換えると以下のエラーが出ることはわかりました。

```

    $ python trial.py
    Traceback (most recent call last):
      File "trial.py", line 6, in <module>
        print(json_object["sandwich"]["order"]["combinations"])
    TypeError: list indices must be integers or slices, not str
    
```
CC BY-SA 4.0
2020-07-07T06:28:47.890
68360
2020-07-07T08:24:11.887
2020-07-07T08:01:59.780
3060
32568
question
python python3 json file-io
jsonであるキーに対する値を取得し、値に応じて要素を追加したい
> `TypeError: list indices must be integers or slices, not str` エラーが出る

`json_object["sandwich"]["order"]`の下は`{ "json": "ではなく" }`、`[ 配列
]`になっているのでエラーが出ます。  
配列の先頭を選べばエラーになりませんので、下記のように書き換えてください。[関連質問](https://ja.stackoverflow.com/a/51775)

修正前: `print(json_object["sandwich"]["order"]["combinations"])`  
修正後: `print(json_object["sandwich"]["order"][0]["combinations"])`

>   1. 「"combinations"」の値を変数に格納して、
>   2. 「bread, vegitables, meats」の"name"と一致するか全て探索を行い
>   3. 一致したもののidを別の変数に格納して
>   4. orderのcombination全体を書き換える
>

サンプルコードが参考になるかもしれません。

```

    import json
    
    json_file = open('sample.json', 'r')
    json_object = json.load(json_file)
    print(json_object["sandwich"]["order"][0]["combinations"]) #これならエラーにならない
    
    # 品目リストごとに変数化する
    breads = json_object["sandwich"]["breads"]
    vegitables = json_object["sandwich"]["vegitables"]
    meats = json_object["sandwich"]["meats"]
    orders = json_object["sandwich"]["order"]
    
    # breadsなどの品目リストからnameが一致する品目を取得する
    def get_item(items, name):
        # 2. 「bread, vegitables, meats」の"name"と一致するか全て探索を行い
        for item in items:
            if item["name"] == name:
                return item
        return None
    
    # bread_nameなどの品目名ごとに一致する品目に書き換える
    def set_combination(order, items, name_key, new_key):
        # 1. 「"combinations"」の値を変数に格納して、
        name = order["combinations"][name_key]
        item = get_item(items, name)
        # 3. 一致したもののidを別の変数に格納して
        del order["combinations"][name_key]
        order["combinations"][new_key] = item
    
    # 4. orderのcombination全体を書き換える
    for order in orders:
        set_combination(order, breads, "bread_name", "bread")
        set_combination(order, vegitables, "vegi_name", "vegitable")
        set_combination(order, meats, "meat_name", "meat")
    
    print(json.dumps(orders, indent=4))
    
```
CC BY-SA 4.0
2020-07-07T08:24:11.887
68364
2020-07-07T08:24:11.887
9820
68360
answer