JSON к экземпляру класса? - PullRequest
       4

JSON к экземпляру класса?

0 голосов
/ 08 февраля 2020

У меня есть простой класс и JSON:

@dataclass
class Point:
    x: int
    y: int

jsonString = '{"x": 3, "y": 5}'

Я хочу преобразовать данные JSON в экземпляр точки. с C# это просто:

JsonConvert.DeserializeObject<Point>(jsonString);

Как я могу это сделать в Python?

Ответы [ 3 ]

0 голосов
/ 08 февраля 2020

Вы можете использовать выражение генератора для получения соответствующих значений, декодируя строку, затем перебирая значения, соответствующие x и y.

>>> from operator import itemgetter
>>> coords = itemgetter('x', 'y')
>>> Point(*(int(x) for x in coords(json.loads(jsonString))))
Point(x=3, y=5)

coords - это функция, которая возвращает кортеж, состоящий из значений x и y его аргумента. Выражение генератора гарантирует, что каждое значение преобразуется в int, а синтаксис * распаковывает генератор в отдельные аргументы.

Однако более идиоматическим решением c было бы определение метода класса для создания Point с учетом соответствующего объекта:

@dataclass
class Point:
    x: int
    y: int

    @classmethod
    def from_dict(cls, d):
        return cls(d['x'], d['y'])

p = Point.from_dict(json.loads(jsonString))

Вы также можете определить from_json метод класса для переноса from_dict:

@dataclass
class Point:
    x: int
    y: int

    @classmethod
    def from_dict(cls, d):
        return cls(d['x'], d['y'])

    @classmethod
    def from_json(cls, j):
        return cls.from_dict(json.loads(j))

p = Point.from_json(jsonString)

Хотя здесь это не показано, методы класса предоставляют места для проверки переданной JSON строки или аргумента, поэтому вы можете более изящно обрабатывать такие вещи, как отсутствующие ключи, дополнительные ключи, JSON значения, которые не являются объектами и т. д. c.

0 голосов
/ 09 февраля 2020

Если «простой класс» реализован как dataclass, как показано в вашем вопросе, данные JSON могут быть десериализованы с помощью функции generi c deserialize_dataclass, показанной ниже.

dataclasses позволяет довольно легко анализировать декорированные классы, а информацию можно использовать для извлечения и преобразования JSON объекта, представленного строкой.

import dataclasses
import json
dataclass = dataclasses.dataclass

def deserialize_dataclass(DataClass, json_string):
    """ Convert the JSON object represented by the string into the dataclass
        specified.
    """
    json_obj = json.loads(json_string)
    dc_data = {field.name: field.type(json_obj[field.name])
                    for field in dataclasses.fields(DataClass)}
    return DataClass(**dc_data)

@dataclass
class Point:
    x: int
    y: int


json_string = '{"x": "3", "y": "5"}'
pt = deserialize_dataclass(Point, json_string)
print(pt)  # -> Point(x=3, y=5)
0 голосов
/ 08 февраля 2020

Как насчет этого?

РЕДАКТИРОВАТЬ: вы также можете конвертировать x и y в целые, если они изначально были строками:

# define Point class:
class Point():

    # define init function:
    def __init__(self, data):
        self.x = int(data['x'])
        self.y = int(data['y'])


# your json point:
json_data = {'x' : '2', 'y' : '3'}

# convert to Point class:
my_point = Point(json_data)

print(my_point)
print(my_point.x)
print(my_point.y)        
...