SuperObject と TJson.ObjectToJsonObject がクラスの特定の部分 (つまり、Record フィールド) を表す方法には一貫性がありません。次のコード スニペットを見てみましょう。
Uses rest.json, superobject;
type
TSimplePersonRec = record
FirstName: string;
LastName: string;
Age: byte;
end;
TSimplePerson = class
protected
FPersonRec: TSimplePersonRec;
public
property personRecord: TSimplePersonRec read FPersonRec write FPersonRec;
end;
// ...
{ Public declarations }
function toJson_SO(simplePerson: TSimplePerson): string;
function toJson_Delphi(simplePerson: TSimplePerson): string;
// ...
function TForm1.toJson_Delphi(simplePerson: TSimplePerson): string;
begin
result := tjson.Format(TJson.ObjectToJsonObject(simplePerson));
end;
function TForm1.toJson_SO(simplePerson: TSimplePerson): string;
var
so: ISuperObject;
ctx: TSuperRttiContext;
begin
ctx := TSuperRttiContext.Create;
try
so := ctx.AsJson<TSimplePerson>( simplePerson );
finally
ctx.Free;
end;
result := so.AsJSon(true, true);
end;
// ...
procedure TForm1.Button3Click(Sender: TObject);
var
spr: TSimplePersonRec;
sp: TSimplePerson;
begin
spr.FirstName := 'John';
spr.LastName := 'Doe';
spr.Age := 39;
sp := TSimplePerson.Create;
sp.personRecord := spr;
memo1.Lines.Add(#13'--- SuperObject ---'#13);
memo1.Lines.Add(toJson_SO(sp));
memo1.Lines.Add(#13'--- Delphi ---'#13);
memo1.Lines.Add(toJson_Delphi(sp));
end;
出力は次のとおりです。
--- SuperObject ---
{
"FPersonRec": {
"LastName": "Doe",
"Age": 39,
"FirstName": "John"
}
}
--- Delphi ---
{
"personRec":
[
"John",
"Doe",
39
]
}
Delphi がレコードを JSON 配列として表現する理由は何ですか? これにつながる公的基準または提案はありますか?
注: 私にとっては、配列ではなく {key: value} 表記でレコードを表す方が自然です。値が属するキー名がわからない場合、逆シリアル化中に奇妙な結果が生じる可能性があります。たとえば、逆シリアル化中に、異なるメモリ レイアウトのレコードを含む、同じレイアウトの新しいクラスを渡すことができます。この場合、値はランダムに割り当てられますか、それとも AV が発生する可能性がありますか?
更新: Delphi XE7 を使用しています。また、json.orgのこれを見つけました:
JSON は、次の 2 つの構造で構築されています。
- 名前と値のペアのコレクション。さまざまな言語で、これはオブジェクト、レコード、構造体、辞書、ハッシュ テーブル、キー付きリスト、または連想配列として実現されます。
- 値の順序付きリスト。ほとんどの言語では、これは配列、ベクトル、リスト、またはシーケンスとして実現されます。
おそらく問題は、これは TJson ユニットのバグですか?