Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi Rest.JSON JsonToObject仅适用于f变量_Json_Rest_Delphi_Vcl_Delphi Xe8 - Fatal编程技术网

Delphi Rest.JSON JsonToObject仅适用于f变量

Delphi Rest.JSON JsonToObject仅适用于f变量,json,rest,delphi,vcl,delphi-xe8,Json,Rest,Delphi,Vcl,Delphi Xe8,我使用的是DelphiXe8 我只是在看REST.Json ObjectToJsonString()和JsonToObject()调用 主要是尝试这样做: 我注意到,只有当变量以F字符开头时,我才能让变量工作。我找不到这方面的任何文档。这是预期的行为吗?我应该在开始时用F命名类中的所有变量吗?如果是,有人能解释一下原因吗 我创建了一个类TTestJSON,定义了两个成员变量,并将它们设置为“WORKS”和“FAILS” 然后,我从该对象创建了一个JSON字符串值: { “varthatwork

我使用的是DelphiXe8

我只是在看
REST.Json ObjectToJsonString()
JsonToObject()
调用

主要是尝试这样做:

我注意到,只有当变量以
F
字符开头时,我才能让变量工作。我找不到这方面的任何文档。这是预期的行为吗?我应该在开始时用
F
命名类中的所有变量吗?如果是,有人能解释一下原因吗

我创建了一个类
TTestJSON
,定义了两个成员变量,并将它们设置为“WORKS”和“FAILS”

然后,我从该对象创建了一个JSON字符串值:

{
“varthatworksbeaceitstartswithf”:“WORKS”,
“sVarThatFailsBecauseItStartsWithS”:“失败”
} 
从JSON字符串返回到对象时,只有
fVarThatWorksBeacuseItStartsWithF
变量被正确重置。在下面的代码中,
test:=TJson.JsonToObject(JsonStr)
使用上述JSON,请注意
svarthatFailsbecauseitsStartSwiths
,而不是
“FAILS”

程序TForm3.btn1Click(发送方:TObject);
变量
测试:TTestJSON;
JsonStr:String;
开始
m1.清除;
test:=TTestJSON.Create;
尝试
test.fVarthatWorksbeaceitstarts,f:=“工程”;
test.sVarThatFailsBecauseItStartsWithS:=“失败”;
JsonStr:=TJson.ObjectToJsonString(test);
最后
免费测试;
结束;
m1.行。添加('**JSONStr值开始**'+#13#10+JSONStr+'**JSONStr值结束**'+#13#10);
test:=TJson.JsonToObject(JsonStr);
尝试
m1.Lines.Add('**Obj从JSON字符串开始加载**'+#13#10+TJson.ObjectToJsonString(test)+#13#10+'**Obj从JSON字符串结束加载**');
最后
免费测试;
结束;
结束;
从结果来看,以
f
开头的var从JSON字符串中去掉了
f
,而以
s
开头的var仍然保留在JSON字符串中。我本以为第二个结果会是这样的:

{
“varthatworksbeaceitstartswithf”:“WORKS”,
“sVarThatFailsBecauseItStartsWithS”:“失败”
}
下面是要复制的完整代码—在vcl表单上有一个按钮和一个备忘录—也使用REST.Json:

unitmain;
接口
使用
Winapi.Windows、Winapi.Messages、System.SysUtils、System.Variants、System.Classes、Vcl.Graphics、,
控件、窗体、对话框、StdCtrls、rest.Json;
类型
TTestJSON=class
fVarthatWorksbeaceitstartswithf:String;
svarthattfailsbecauseitstartswiths:String;
结束;
TForm3=类别(TForm)
btn1:TButton;
m1:TMemo;
程序btn1Click(发送方:TObject);
私有的
{私有声明}
公众的
{公开声明}
结束;
变量
表3:TForm3;
实施
{$R*.dfm}
程序TForm3.btn1Click(发送方:TObject);
变量
测试:TTestJSON;
JsonStr:String;
开始
m1.清除;
test:=TTestJSON.Create;
尝试
test.fVarthatWorksbeaceitstarts,f:=“工程”;
test.sVarThatFailsBecauseItStartsWithS:=“失败”;
JsonStr:=TJson.ObjectToJsonString(test);
最后
免费测试;
结束;
m1.行。添加('**JSONStr值开始**'+#13#10+JSONStr+'**JSONStr值结束**'+#13#10);
test:=TJson.JsonToObject(JsonStr);
尝试
m1.Lines.Add('**Obj从JSON字符串开始加载**'+#13#10+TJson.ObjectToJsonString(test)+#13#10+'**Obj从JSON字符串结束加载**');
最后
免费测试;
结束;
结束;
结束。

Delphi中的JSON序列化基于字段,而不是属性。但是大多数Delphi类都有友好的属性和F前缀字段。和此同时,Emb似乎正试图避免在生成的JSON中使用F前缀名称。当序列化字段时,他们从名称中删除第一个“F”,并在从JSON读取时将其添加回(以找到正确的字段)。似乎在Delphi中使用JSON序列化的唯一(安全)方法是将所有字段名保留为前缀“F”(对于要序列化的字段):

更新2:正如David提到的,我们可以使用属性,然后我们就有了更好的控制:

uses
  REST.Json.Types, // without this unit we get warning: W1025 Unsupported language feature: 'custom attribute'
  REST.Json;

type
  // All fields of records are serialized, no control here.
  TRec = record
    RecStr: String;
  end;

  // By default all fields of class are serialized, but only F-prefixed serialized correctly.
  // We can use JSONMarshalled attribute to enable/disable serialization.
  // We can use JSonName attribute to serialize field with specific name in JSON.
  TTestJSON = class
    [JSONMarshalled(True)] [JSonName('RecField')]
    R: TRec;
  end;

procedure TForm28.FormCreate(Sender: TObject);
var
  Test: TTestJSON;
  JsonStr: string;
begin
  Test := TTestJSON.Create;
  try
    Test.R.RecStr := 'Some str';
    JsonStr := TJson.ObjectToJsonString( Test );
  finally
    FreeAndNil(Test);
  end;

  // JsonStr: {"RecField":["Some str"]}

  Test := TJson.JsonToObject<TTestJSON>(JsonStr);
  FreeAndNil(Test);
end;
使用
REST.Json.Types,//如果没有此单元,我们将收到警告:W1025不支持的语言功能:“自定义属性”
REST.Json;
类型
//所有记录字段都是序列化的,此处没有控件。
TRec=记录
RecStr:字符串;
结束;
//默认情况下,类的所有字段都是序列化的,但只有带F前缀的字段被正确序列化。
//我们可以使用JSONMarshalled属性来启用/禁用序列化。
//我们可以使用JSonName属性来序列化JSON中具有特定名称的字段。
TTestJSON=class
[JSONMarshalled(True)][JSonName('RecField')]
R:TRec;
结束;
程序TForm28.FormCreate(发送方:TObject);
变量
测试:TTestJSON;
JsonStr:string;
开始
Test:=TTestJSON.Create;
尝试
Test.R.RecStr:=“一些str”;
JsonStr:=TJson.ObjectToJsonString(Test);
最后
FreeAndNil(测试);
结束;
//JsonStr:{“RecField”:[“Some str”]}
Test:=TJson.JsonToObject(JsonStr);
FreeAndNil(测试);
结束;

此库序列化字段。由于通常的做法是在字段前面加上字母F,因此设计人员希望从JSON中使用的名称中删除该字母。因此,他们决定将默认行为设置为在名称以F开头的字段中去掉第一个字母。坦白说,我觉得这很奇怪

可以使用属性自定义此行为。例如:

[JSONMarshalled(False)]
FFoo: Integer; 

[JSONMarshalled(True)]
[JSONName('Blah')]
Bar: Integer;

据我所知,这些都没有得到适当的记录

变量名是不相关的,除非它们会导致不同范围的命名冲突。在您的示例中,什么“不起作用”?请描述实际问题。@Remy不在这里。在他们无限的智慧中,Emba决定序列化第一个字母为F的变量。所以弗雷德来了,但乔治留下了。@Danga是的,文档在这里并不存在。使用
JSONMarshalled
[JSONMarshalled(False)] FFoo: Integer; [JSONMarshalled(True)] [JSONName('Blah')] Bar: Integer;