Delphi(Tokyo)でJson形式のファイルを読み込む必要が出てきたので、Json.NETのような書き方ができなか調べていたところもう1年くらい前の記事になりますが、
@lynatan さんのTJsonSerializerの記事
TJsonSerializerの使い方。
TJsonSerializerの実用例
エンバカデロさんのブログ
TJsonSerializerでJSONに変換する[JAPAN]
DelphiでもTokyoになって、Json.NETのような書き方ができるようになっているとのことでしたので、試して見ました。
読み書きするのは、以下のような内容のファイル
{"ShopName":"ラビットハウス",
"Clerks":[
{"Name":"ココア","Age":17},
{"Name":"チノ","Age":15},
{"Name":"リゼ","Age":17}
]
}
上記の構造にマップできるクラスを作成します。
先ずは、従業員(Clerk)クラス。
パブリックメンバーをシリアライズ対象のするのでクラスに[JsonSerialize(TJsonMemberSerialization.&Public)]
属性を付加しています。
(余談ですが、予約語、指令と被るワードを使う場合、その前に"&"が必要です。)
- unit Unit1;
- //パブリックメンバーをシリアライズ対象にする属性
- [JsonSerialize(TJsonMemberSerialization.&Public)]
- TClerk = class
- private
- FName: string;
- FAge: integer;
- procedure SetAge(const Value: integer);
- procedure SetName(const Value: string);
- public
- property Name : string read FName write SetName;
- property Age : integer read FAge write SetAge;
- constructor Create; overload;
- constructor Create(const vName : string; const vAge : integer); overload;
- end;
次に喫茶店(CoffeeShop)クラスの定義
- [JsonSerialize(TJsonMemberSerialization.&Public)]
- TCoffeeShop = class
- private
- FClerks: TList<TClerk>;
- FShopName: string;
- procedure SetClerks(const Value: TList<TClerk>);
- procedure SetShopName(const Value: string);
- public
- property ShopName : string read FShopName write SetShopName;
- //TClerkクラスのジェネリックリスト用のコンバーターを登録
- [JsonConverter(TJsonClerkListConverter)]
- property Clerks : TList<TClerk> read FClerks write SetClerks;
- public constructor Create;
- end;
メンバーは、喫茶店名と、従業員のリスト(ジェネリックのリスト)です。
こちらも、パブリックメンバーをシリアル化の対象とします。
ジェネリックのリストは、そのままではシリアライズできないので、Json.Converterユニットに定義済みの TJsonListConverter
- //TClerk型のリスト用のコンバーター
- TJsonClerkListConverter = class(TJsonListConverter<TClerk>);
を作成し、TClerk型のジェネリックリスト型のメンバーClerks用のコンバーター属性を付加しています。
クラス定義の全体は、以下とおりです。
- unit Unit2;
- interface
- uses
- //Json.SerializersとConverterを使用する。
- System.JSON.Serializers
- , System.JSON.Converters
- //TList<t>を使用する
- , System.Generics.Collections
- ;
- type
- //パブリックメンバーをシリアライズ対象にする属性
- [JsonSerialize(TJsonMemberSerialization.&Public)]
- TClerk = class
- private
- FName: string;
- FAge: integer;
- procedure SetAge(const Value: integer);
- procedure SetName(const Value: string);
- public
- property Name : string read FName write SetName;
- property Age : integer read FAge write SetAge;
- constructor Create; overload;
- constructor Create(const vName : string; const vAge : integer); overload;
- end;
- //TClerk型のリスト用のコンバーター
- TJsonClerkListConverter = class(TJsonListConverter<TClerk>;);
- [JsonSerialize(TJsonMemberSerialization.&Public)]
- TCoffeeShop = class
- private
- FClerks: TList<TClerk>;
- FShopName: string;
- procedure SetClerks(const Value: TList<TClerk>);
- procedure SetShopName(const Value: string);
- public
- property ShopName : string read FShopName write SetShopName;
- //TClerkクラスのジェネリックリスト用のコンバーターを登録
- [JsonConverter(TJsonClerkListConverter)]
- property Clerks : TList<TClerk> read FClerks write SetClerks;
- public constructor Create;
- end;
- implementation
- { TClerk }
- constructor TClerk.Create(const vName: string; const vAge: integer);
- begin
- FName := vName;
- FAge := vAge;
- end;
- constructor TClerk.Create;
- begin
- end;
- procedure TClerk.SetAge(const Value: integer);
- begin
- FAge := Value;
- end;
- procedure TClerk.SetName(const Value: string);
- begin
- FName := Value;
- end;
- { TCoffeeShop }
- constructor TCoffeeShop.Create;
- begin
- FClerks := TList<TClerk>.Create;
- end;
- procedure TCoffeeShop.SetClerks(const Value: TList<TClerk>);
- begin
- FClerks := Value;
- end;
- procedure TCoffeeShop.SetShopName(const Value: string);
- begin
- FShopName := Value;
- end;
- end.
上記で定義したクラスに対で、冒頭で示した内容のJson形式の定義ファイルCoffeeShop.Jsonを読み込み、デシリアライズする処理は、以下のとおりとなります。
- procedure TForm1.Button2Click(Sender: TObject);
- var
- CoffeeShop : TCoffeeShop;
- serializer: TJsonSerializer;
- s : string;
- Clerk : TClerk;
- begin
- s := TFile.ReadAllText('CoffeeShop.Json',TEncoding.UTF8);
- serializer := TJsonSerializer.Create;
- try
- CoffeeShop := serializer.Deserialize<TCoffeeShop>(s);
- try
- Memo1.Clear;
- Memo1.Lines.Add(CoffeeShop.ShopName);
- for Clerk in CoffeeShop.Clerks do
- begin
- Memo1.Lines.Add(Clerk.Name + '(' + Clerk.Age.ToString() + ')');
- end;
- finally
- CoffeeShop.Clerks.Clear();
- CoffeeShop.Free;
- end;
- finally
- serializer.Free
- end;
ファイルを読み込み、シリアライザーを生成し、読み込んだJson文字列をデシリアライズして、ショップ名と、店員の情報をメモに表示しています。 (余談ですが、クラス定義で属性を使用しないで、TJsonSerializerインスタンスのConverterリストにTJsonClerkListConverterのインスタンスを登録してもデシリアライズできます。)
冒頭で示した内容のJson形式の定義ファイルを作成する場合は、以下の処理でできます。
- procedure TForm1.Button1Click(Sender: TObject);
- var
- CoffeeShop : TCoffeeShop;
- serializer: TJsonSerializer;
- s : string;
- begin
- CoffeeShop := TCoffeeShop.Create;
- try
- CoffeeShop.ShopName := 'ラビットハウス';
- CoffeeShop.Clerks.Add(TClerk.Create('ココア',17));
- CoffeeShop.Clerks.Add(TClerk.Create('チノ',15));
- CoffeeShop.Clerks.Add(TClerk.Create('リゼ',17));
- serializer := TJsonSerializer.Create;
- try
- s := serializer.Serialize(CoffeeShop);
- Memo1.Text := s;
- TFile.WriteAllText('CoffeeShop.Json',s);
- finally
- serializer.Free;
- end;
- finally
- CoffeeShop.Clerks.Clear();
- CoffeeShop.Free;
- end;
- end;
TCoffeeShop型のインスタンスを生成し、メンバーを設定後、シリアライザーを生成しシリアライズ後、ファイルに保存しています。
(確認の為、画面上のメモにも表示しています。)
プロジェクト一式は、https://bitbucket.org/OldTPFun/delphitest/src/master/JsonTest/Proj1/
に配置しております。
0 件のコメント:
コメントを投稿