LoginSignup
6

More than 5 years have passed since last update.

JSON変換するクラス

Last updated at Posted at 2012-03-16

継承して, convertersにそれぞれの属性をJSON化可能なオブジェクトに変換するときに使うcallableなオブジェクトを詰めておく.

seri.py
import json
from unittest import TestCase
import unittest

class JSONSerializable(object):
    """Serialize to json. """

    def to_json(self, exclude=tuple()):
        """
        exclude: List or tuple of attributes that is excluded to serialize.
        """
        data = self.to_serializable_dict(exclude=exclude)
        return json.dumps(data, ensure_ascii=False)

    def to_serializable_dict(self, exclude=tuple()):
        """Convert to dict that is json serializable.
        exclude: List or tuple of attributes that is excluded to serialize.
        """
        data = {}
        for attr, conv in self.converters:
            if attr in exclude:
                continue
            if not hasattr(self, attr):
                continue
            value = getattr(self, attr, None)
            data[attr] = conv(value) if value is not None else None
        return data

class TestJSONSerializable(TestCase):

    def test_1(self):
        """Call to_serializable_dict()."""

        class C(JSONSerializable):
            b = None
            c = 0
            x = 3

            def __init__(self):
                self.y = 4

            @property
            def z(self):
                return 5

            # Convert to prefered type.
            converters = (
                ('a', int),
                ('b', int),
                ('x', int),
                ('y', float),
                ('z', unicode),
                )

        # Try.
        c = C()
        res = c.to_serializable_dict()

        # Verify
        self.assertEqual(set(res.keys()), set(('b', 'x', 'y', 'z')))
        self.assertEqual(res['b'], None)
        self.assertEqual(res['x'], 3)
        self.assertEqual(res['y'], 4.0)
        self.assertEqual(res['z'], u'5')

        return

    def test_2(self):
        """Call to_serializable_dict() with exclude."""

        class C(JSONSerializable):
            x = 3

            def __init__(self):
                self.y = 4

            @property
            def z(self):
                return 5

            # Convert to prefered type.
            converters = (
                ('x', int),
                ('y', float),
                ('z', unicode),
                )

        # Try.
        c = C()
        res = c.to_serializable_dict(exclude=('x','z'))

        # Verify
        self.assertEqual(set(res.keys()), set('y'))
        self.assertEqual(res['y'], 4.0)

        return

    def test_3(self):
        """Call to_json()."""

        from json import loads

        class C(JSONSerializable):
            x = 3

            def __init__(self):
                self.y = 4

            @property
            def z(self):
                return 5

            # Convert to prefered type.
            converters = (
                ('x', int),
                ('y', float),
                ('z', unicode),
                )

        # Try.
        c = C()
        res = c.to_json()

        # Verify
        res_dict = loads(res)
        self.assertEqual(res_dict['x'], 3)
        self.assertEqual(res_dict['y'], 4.0)
        self.assertEqual(res_dict['z'], u'5')

        return

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6