Как десериализовать JSON с необязательными полями, используя attrs и cattrs - PullRequest
0 голосов
/ 26 декабря 2018

Я хочу десериализовать документы MongoDB, используя attr и cattrs.Поскольку у noSQL нет фиксированной схемы, мне нужно как-то указать на attr.ib-ы, что они могут быть пропущены, и не добавлять их в объект dict в этом случае.

Я использовал colander прежде, чтобы делать подобные вещи, и он предоставляет «отсутствующий» параметр в конструкторе colander.SchemaNode, который делает именно это, передавая colander.drop в качестве аргумента.Мне интересно, как сделать то же самое с этими библиотеками, я не нашел ничего в документации.Итак:

import attr
from cattr import structure

@attr.s
class ABC:
    A: float = attr.ib()
    B: float = attr.ib()
    C: float = attr.ib()

d = {'A': 1, 'B': 2}
obj = structure(d, ABC)

Должен возвращать объект только с атрибутами A и B.Я пробовал с некоторыми параметрами (init, default ...) и даже с помощью Optional класса, набирающего lib, но все методы, которые я пробовал, возвращали атрибут каким-то образом.

Спасибо за вашу помощь.

1 Ответ

0 голосов
/ 06 января 2019

(я автор cattrs и основной участник attrs.)

Hello,

класс Python attrs по определению будет иметь все свои поля в экземпляре__dict__.Когда вы говорите, что структурирование «должно возвращать объект только с атрибутами A и B», я предполагаю, что вы хотите, чтобы возвращаемый экземпляр выдавал AttributeError при попытке доступа к obj.C.

Насколько мне известно, этоневозможно с attrs, и при этом это не в духе attrs.Вы определили, что ваш класс имеет три атрибута, поэтому он должен иметь значения в этих атрибутах.

Что вы можете сделать, это использовать None в качестве маркера значения для отсутствующего значения;это обычный способ представления отсутствующих значений в Python в целом.Фрагмент кода становится следующим:

from typing import Optional

import attr
from cattr import structure

@attr.s
class ABC:
    A: float = attr.ib()
    B: float = attr.ib()
    C: Optional[float] = attr.ib(default=None)

d = {'A': 1, 'B': 2}
obj = structure(d, ABC)

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

...