@AlexanderMi
Software Developer

Как указать когда нужна рекурсия а когда нет?

Привет!

Есть библиотека книг (класс BookLibrary), у библиотеки может быть много полок (класс BookShelf), у каждой полки много книг (клас Book).
Книга содержит в себе ссылку на полку, на которой стоит эта книга.

Как добиться того чтобы при сериализации в JSON всей полки книг, каждая книга содержала в себе ссылку на полку с книгой, без списка книг на полке, а при сериализации книги, ссылка на полку так же в себе имела и список книг?

Сейчас и тот и другой вариант возвращают какой-то ад..

Код
import jsons
from dataclasses import dataclass
from typing import List

  
@dataclass
class BookShelf:
    name: str
    books: List # list of Book
    
    def __init__(self, name):
        self.name = name
        self.books = list()
  
@dataclass
class Book:
    name: str
    shelf: BookShelf

    def __init__(self, name, shelf):
        self.name = name
        self.shelf = shelf
  

@dataclass
class BookLibrary:
    name: str
    shelfes: List[BookShelf]
    
    def __init__(self, name):
        self.name = name
        self.shelfes = list()
    
def run():
    lib = BookLibrary(name = 'Books library')
    shelf = BookShelf(name = 'python')
    
    book = Book(name = 'Alice in wonderlands', shelf = shelf)
    shelf.books.append(book)
    
    lib.shelfes.append(shelf)
    
    
    
    print('JSON:\n'+jsons.dumps(lib))
    
if __name__ == '__main__':
    try:
        run()
    except SystemExit:
        pass


Результат

{
    "name": "Books library",
    "shelfes": [{
            "books": [{
                    "name": "Alice in wonderlands",
                    "shelf": {
                        "books": [{
                                "name": "Alice in wonderlands",
                                "shelf": {
								   # repeating shelf/books/shelf/books..
                            }
                        ],
                        "name": "python"
                    }
                }
            ],
            "name": "python"
        }
    ]
}

  • Вопрос задан
  • 88 просмотров
Решения вопроса 1
Vindicar
@Vindicar
RTFM!
JSON не предназначен для структур данных с циклическими ссылками. Вообще-то ты должен был словить исключение в этом случае, а не рекурсию. Очень странно, что этого не произошло.
Тут есть две возможности:
1. Задуматься о смысле жизни, а на кой тебе вообще обратные ссылки? Они тебе ТОЧНО необходимы? У тебя есть сценарий, когда у тебя есть ссылка на книгу, но нет необходимой ссылки на полку? Книга должна что-то знать о полке. на которой она стоит? Если без них можно обойтись, удали их. Проще жить будет. Подумай, например, что при перемещении книги с полки на полку ты должен не забыть сменить книге shelf.
2. Посмотреть на параметр default в json.dump(). Это должна быть функция, которая принимает объект, и возвращает словарь. Ты можешь явно проверять, что объект - один из твоих датаклассов, и удалять из полученного словаря обратные ссылки. Аналогично, у json.load() есть object_hook, который позволяет задать свою логику превращения загруженных из JSON словарей в объекты. Но серьёзно, так ли нужны обратные ссылки?
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы