web-dev-qa-db-ja.com

jsonをオブジェクトに変換する方法は?

Json-stringをpythonオブジェクトに変換する必要があります。オブジェクトとは、次のような「新しい」python3オブジェクトを意味します。

class MyClass(object):

たとえば、jsonpickleのドキュメントでいくつかのヘルプを見つけました。しかし、私が見つけたのは、最初にオブジェクトをjsonに変換し、その後逆方向に変換するチュートリアルだけです。

Rest-API からjson-stringを変換したい。

これが私がこれまでにしたことです:

import requests
import jsonpickle

class Goal(object):
    def __init__(self):
        self.GoaldID = -1
        self.IsPenalty = False

class Match(object):
    def __init__(self):
        self.Goals = []

headers = {
    "Content-Type": "application/json; charset=utf-8"
}

url = "https://www.openligadb.de/api/getmatchdata/39738"

result = requests.get(url=url, headers=headers)
obj = jsonpickle.decode(result.json)
print (obj)

その結果、次のようになります。

TypeError: the JSON object must be str, bytes or bytearray, not 'method'

Jsonpickleがどのクラスで出力を変換する必要があるかを教えていないので、jsonpickleがこれを私のクラス(Goal、Match)に変換できないことは私には非常に明白です。問題は、オブジェクトのJSONをMatch型から変換するようにjsonpickleに指示する方法がわからないことです。また、目標のリストがList<Goal>タイプである必要があることをどのように判断できますか?

10
Sebi

次の行はあなたに辞書を与えるでしょう:

obj = jsonpickle.decode(result.content)  # NOTE: `.content`, not `.json`

obj = result.json()

しかし、上記のどれもあなたが望むものをあなたに与えません(pythonオブジェクト(二分法ではありません))。 URLのjsonはjsonpickle.encodeでエンコードされていないため-生成されたjsonに追加情報を追加します({"py/object": "__main__.Goal", ....}など)


>>> import jsonpickle
>>> class Goal(object):
...     def __init__(self):
...         self.GoaldID = -1
...         self.IsPenalty = False
...
>>> jsonpickle.encode(Goal())
'{"py/object": "__main__.Goal", "IsPenalty": false, "GoaldID": -1}'
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# JSON encoded with jsonpickle.encode  (default unpicklable=True)
#   => additional python class information attached
#   => can be decoded back to Python object
>>> jsonpickle.decode(jsonpickle.encode(Goal()))
<__main__.Goal object at 0x10af0e510>


>>> jsonpickle.encode(Goal(), unpicklable=False)
'{"IsPenalty": false, "GoaldID": -1}'
# with unpicklable=False   (similar output with json.dumps(..))
#   => no python class information attached
#   => cannot be decoded back to Python object, but a dict
>>> jsonpickle.decode(jsonpickle.encode(Goal(), unpicklable=False))
{'IsPenalty': False, 'GoaldID': -1}

辞書ではない実際のPythonオブジェクトが必要な場合、つまりdic.Goals.[0].GoalGetterNameよりもdic["Goals"][0]["GoalGetterName"]を好む場合は、 json.loads を使用します。 object_hookを使用:

import json
import types    
import requests

url = "https://www.openligadb.de/api/getmatchdata/39738"

result = requests.get(url)
data = json.loads(result.content, object_hook=lambda d: types.SimpleNamespace(**d))
# OR   data = result.json(object_hook=lambda d: types.SimpleNamespace(**d))
goal_getter = data.Goals[0].GoalGetterName
# You get `types.SimpleNamespace` objects in place of dictionaries
7
falsetru

このような意味ですか?

import json

class JsonObject(object):   

    def __init__(self, json_content):
        data = json.loads(json_content)
        for key, value in data.items():
            self.__dict__[key] = value      


jo = JsonObject("{\"key1\":1234,\"key2\":\"Hello World\"}")
print(jo.key1)

印刷するもの:

1234
[Finished in 0.4s]
5
Den1al

最近のpythonバージョンでのクリーンなアプローチは Marshmallow-dataclass

from dataclasses import field
from Marshmallow_dataclass import dataclass 
from typing import List

@dataclass
class Goal:
    GoaldID: int = field(default=-1)
    IsPenalty: bool = field(default=False)


@dataclass
class Match:
    Goals: List[Goal] = field(default_factory=lambda: [])

my_match, _ = Match.Schema().load(result.json())
0
lovasoa