0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ある同一のデータを別々のプログラミング言語で扱うといったケースは少なくないかと思います。例えば、API経由でのデータのやり取りや、データの加工や分析だけちょっとpythonを使いたいなどですかね。
そこで今回はJSON形式でのインターフェースとなるようなクラスをとりあえずpythonで用意できないかと考えました。

1. シリアライズ可能なフィールドを持つクラスの例

メインはto_json関数とfrom_json関数です

  • to_json : 生成したオブジェクトからstringのjsonを生成します
  • from_json : stringのjsonからオブジェクトを生成します
import json

class PersonClass:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def to_json(self):
        return json.dumps(self.__dict__)

    @classmethod
    def from_json(cls, json_string):
        data = json.loads(json_string)
        return cls(**data)

    def __eq__(self, other):
        if isinstance(other, PersonClass):
            return self.__dict__ == other.__dict__
        return False

    def __hash__(self):
        return hash(tuple(sorted(self.__dict__.items())))

    def __str__(self):
        return f"PersonClass(name={self.name}, age={self.age})"

person_from = PersonClass("bob", 25)
print(person_from) # PersonClass(name=bob, age=25)
print(hash(person_from)) # 4914228952729239745

person_to = PersonClass.from_json(person_from.to_json())
print(person_to) # PersonClass(name=bob, age=25)
print(hash(person_to)) # 4914228952729239745

print(person_from == person_to) # True

2. シリアライズ不可のフィールドがある時

PersonClassがデフォルトでシリアライズ不可能なobject, Enum型のフィールドを持つ場合を考えます。
詳しくはこちらを参照 : https://qiita.com/vossibop/items/b902ceabf199272c9cf4

変更点としては以下です

  • CustomJSONEncoderでシリアライズ時のオブジェクトの型変換などを定義
  • to_json内のjson.dumps()で上記encoderを使用する
  • from_json内のjson.loads()で得たdict型をそのままコンストラクタに渡すとオブジェクトのインスタンス生成がうまくできないので以下のようにして渡す
    • return cls(data['name'], data['age'], Country(**data['country']))
import json
from datetime import date
from enum import Enum

class CustomJSONEncoder(json.JSONEncoder):
    def default(self, obj):
        # Enum -> str,int
        if isinstance(obj, Enum):
            return obj.value
        # datetime -> str
        if isinstance(obj, datetime):
            return obj.isoformat()
        # object -> dict
        elif isinstance(obj, object) and hasattr(obj, '__dict__'):
            return obj.__dict__
        # dict,str,int,... -> default       
        return super().default(obj)
      
class Language(Enum):
    EN = 1
    JA = 2
    FR = 3
    DE = 4
    IT = 5

class Country:
    def __init__(self, name: str, language: int):
        self.name = name
        self.language = Language(language)

    def to_json(self):
        return json.dumps(self.__dict__)

    @classmethod
    def from_json(cls, json_string):
        data = json.loads(json_string)
        return cls(**data)

    def __eq__(self, other):
        if isinstance(other, Country):
            return self.__dict__ == other.__dict__
        return False

    def __hash__(self):
        return hash(tuple(sorted(self.__dict__.items())))

    def __str__(self):
        return f"Country(name={self.name}, language={self.language})"


class PersonClass:
    def __init__(self, name: str, age: int, country: Country):
        self.name = name
        self.age = age
        self.country = country

    def to_json(self, encoder: JSONEncoder):
        return json.dumps(self, cls=encoder)

    @classmethod
    def from_json(cls, json_string):
        data = json.loads(json_string)
        return cls(data['name'], data['age'], Country(**data['country']))

    def __eq__(self, other):
        if isinstance(other, PersonClass):
            return self.__dict__ == other.__dict__
        return False

    def __hash__(self):
        return hash(tuple(sorted(self.__dict__.items())))

    def __str__(self):
        return f"PersonClass(name={self.name}, age={self.age}, country={self.country})"


country = Country("United States", 1)

person_from = PersonClass("bob", 25, country)
print(person_from) # PersonClass(name=bob, age=25, country=Country(name=United States, language=Language.EN))
print(hash(person_from)) # -7954654959397923626

person_to = PersonClass.from_json(person_from.to_json(CustomJSONEncoder))
print(person_to) # PersonClass(name=bob, age=25, country=Country(name=United States, language=Language.EN))
print(hash(person_to)) # -7954654959397923626

print(person_from == person_to) # True
0
0
0

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?