11

我需要将 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 应该在哪个类中转换输出。问题是我不知道如何告诉 jsonpickle 将对象中的 JSON 从匹配类型转换?我怎么知道目标列表应该是 type List<Goal>

4

3 回答 3

9

以下几行将为您提供字典:

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"]object_hook json.loads

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
于 2017-03-08T13:01:30.763 回答
7

你的意思是这样的吗?

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]
于 2017-03-09T09:46:24.290 回答
1

最近的 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())
于 2019-03-12T14:25:30.343 回答