Delphi XE5 RestClient和PHP使用布尔数据类型生成JSON

时间:2014-04-28 19:15:15

标签: android json delphi rest delphi-xe5

我正在使用delphi XE5开发我的第一个Android应用程序。

我需要访问Intranet上运行的PostgreSQL数据库中的数据。

鉴于不建议直接从移动设备访问数据库,我已经安装了Apache Web服务器和PHP应用程序来提供数据。

一切正常,但布尔字段存在问题:

这是一个示例表:

create table resources(
  resource_id integer not null primary key,
  resource_name varchar(50),
  is_working boolean not null default false
);

INSERT INTO resources (resource_id, resource_name, is_working) VALUES (1,'Lathe 01', false);
INSERT INTO resources (resource_id, resource_name, is_working) VALUES (2,'Lathe 02', true);
INSERT INTO resources (resource_id, resource_name, is_working) VALUES (3,'Press 01', true);

PHP脚本在数据库上执行查询:

select * from resources;

并使用json_econder函数以json格式返回数据:

... 
  $r = $dbh->query($sql);
  if ($r) {      
    $f = $r->fetchAll();        
    echo json_encode($f);  
  }
... 

返回的数据如下:

[{"resource_id": 1, "0": 1, "resource_name": "Lathe 01", "1": "Lathe 01", "is_working": false, "2": false}, 
 {"resource_id": 2, "0": 2, "resource_name": "Lathe 02", "1": "Lathe 02", "is_working": true, "2": true} 
 {"resource_id": 3, "0": 3, "resource_name": "Press 01", "1": "Press 01", "is_working": true, "2": true}] 

Delphi程序包含以下组件:

  • RESTClient1:TRestClient
  • RESTResponse1:RESTResponse
  • RestRequest1:TRestRequest
  • RESTResponseDataSetAdapter1:TRESTResponseDataSetAdapter
  • ClientDataSet1:TClientDataset

在组件RESTResponseDataSetAdapter1中 我创建了必要的字段:

  • resource_id(ftInteger)
  • resource_name(ftString)
  • is_working(ftBoolean)

我根据RESTResponseDataSetAdapter1更新了ClientDataSet1字段。

如果我在命令

中运行应用程序
RESTRequest1.Execute; 

引发异常:

  

字段'is_working'的值无效

如果我在调试模式下运行程序会引发两个例外:

  

EVariantTypeCastError,带有消息'Cold not convert variant of type   (UnicodeString)转换为类型(布尔)'

然后:

  

EDatabse错误消息'字段值无效'is_working''

出了什么问题?

1 个答案:

答案 0 :(得分:0)

问题出在单位REST.Response.Adapter中。用于将数据解析为数据集的回调尚未完成。

procedure TCustomJSONDataSetAdapter.CB_CollectFieldDefs(const AJSONObject: TJSONObject);
var
  LJSONPair: TJSONPair;
begin
  for LJSONPair in AJSONObject do
  begin
    DoAddDataSetFieldDef(LJSONPair.JsonString.Value, ftString);
  end;
end;
// and
procedure TCustomJSONDataSetAdapter.CB_CollectFieldDefs(const AJSONObject: TJSONObject);
var
  LJSONPair: TJSONPair;
begin
  for LJSONPair in AJSONObject do
  begin
    DoAddDataSetFieldDef(LJSONPair.JsonString.Value, ftString);
  end;
end;

在您的情况下,由于您手动创建了数据集字段定义,因此未调用CB_CollectFieldDefs。这应该使解析更容易,但遗憾的是并非如此。这是因为TJsonObject中的TJsonPair没有正确解析布尔json值。到调用CB_CollectFieldData时,所有布尔值都是空字符串。所以我们得到异常'无法将类型(UnicodeString)的变体转换为类型(布尔)'。