> For the complete documentation index, see [llms.txt](https://flask-yushu.gitbook.io/yushu/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://flask-yushu.gitbook.io/yushu/6.-shu-ji-xiang-qing-ye-mian-de-gou-jian/6.5-cong-json-xu-lie-hua-kan-dai-ma-jie-shi-quan-fan-zhuan.md).

# 6.5 从json序列化看代码解释权反转

重构完上节课的代码后，如果访问视图函数，是会报json转换异常的错误的，这是因为python不能直接将一个对象序列化成json字符串。下面我们来解决这个问题

虽然对象不能序列化，但是字典是可以的，而python有一个实例变量\_\_dict\_\_来获取一个对象所有属性组成的字典。

但是对于BookCollection这个类实例化的对象来说，不可以，因为他不是一个普通的python对象，他有一个属性是BookViewModel对象（books）。

## 转移解释权

> 我们可以借助一种转移解释权的思想，我们提供一个函数，来序列化对象，当有遇到不可序列化的成员变量时，当我们不知道如何继续序列化的时候，我们可以把这个解释的过程交给函数的调用方，由函数调用方帮我们完成序列化的过程。

## 这种转移解释权的思想可以通过函数式编程的方式非常简单巧妙的实现：

> 我们在编写json.dumps()的时候，要求函数调用方传递一个函数，传递的这个函数的具体实现细节是由函数调用方来完成的，我们不需要关心，这个函数内部的具体实现细节，一旦遇到不能够序列化的类型的时候，我们就调用这个函数。将不可序列化的类型转化成可以序列化的类型。我们只需要关注return的结果。

这就实现了代码解释权的反转，代码的解释权不在由函数编写方来定义，而是把这个权利交给了函数调用方。也是**23种设计模式中的策略模式**

```python
@web.route("/book/search/")
def search():
    """
    搜索书籍路由
    """
    form = SearchForm(request.args)
    if not form.validate():
        return jsonify(form.errors)

    q = form.q.data.strip()
    isbn_or_key = is_isbn_or_key(q)

    books = BookCollection()
    yushu_book = YuShuBook()

    if isbn_or_key == 'isbn':
        yushu_book.search_by_isbn(q)
    else:
        page = form.page.data
        yushu_book.search_by_key(q, page)

    books.fill(yushu_book, q)
    return json.dumps(books, default=lambda o: o.__dict__)
```
