如何获得动态 TClientDataset(基于 TRESTResponseDataSetAdapter)以正确识别布尔值?
How do I get a dynamic TClientDataset (based on TRESTResponseDataSetAdapter) to correctly recognise boolean values?
我在 Delphi XE5 中构建了一个 delphi 客户端示例,它利用了 Rest 库:
- TRestClient
- TRestRequest
- TRestResponse
- TRESTResponseDataSetAdapter
- TClientDataSet(和 TDataSource 绑定到 TDBGrid 和
TcxGridDBTableView)
全部由 ASP.net Web API 提供,该 Web API 根据来自 Delphi 的动态查询生成数据集。我可以成功地向客户端 运行 查询和 return 数据并呈现数据,但是布尔字段呈现为空白。
- 如何让 TClientDataSet 正确识别数据类型?
- 这是使用 TRESTResponseDataSetAdapter 的正确方法还是
TClientDataSet?
- 有没有人对这些组件有任何经验
编辑
令人惊讶的是,Embarcadero 的 TRestResponseDatasetAdapter 在内部执行此操作以创建字段:
procedure TCustomJSONDataSetAdapter.CB_CollectFieldDefs(const AJSONObject: TJSONObject);
var
LJSONPair: TJSONPair;
begin
for LJSONPair in AJSONObject do
begin
DoAddDataSetFieldDef(LJSONPair.JsonString.Value, ftString);
end;
end;
字段类型都硬编码为 ftString!
这是 returned json:
"Table": [
{
"Id": 34,
"Node": "Navision_ASN_1",
"FormatId": 2,
"Value": null,
"ParentID": null,
"DocumentOrder": 1,
"Combined": false,
"Delimiter": "",
"ValueType": 0,
"Ignore": false,
"IsIndexer": false,
"IsCounter": false,
"StringFormat": null
},
{
"Id": 35,
"Node": "MessageHeader",
"FormatId": 2,
"Value": null,
"ParentID": 34,
"DocumentOrder": 2,
"Combined": false,
"Delimiter": "",
"ValueType": 0,
"Ignore": false,
"IsIndexer": false,
"IsCounter": false,
"StringFormat": null
},
{
"Id": 52,
"Node": "Consignment",
"FormatId": 2,
"Value": null,
"ParentID": 34,
"DocumentOrder": 13,
"Combined": false,
"Delimiter": "",
"ValueType": 0,
"Ignore": false,
"IsIndexer": false,
"IsCounter": false,
"StringFormat": null
},
{
"Id": 53,
"Node": "Line",
"FormatId": 2,
"Value": null,
"ParentID": 52,
"DocumentOrder": 18,
"Combined": false,
"Delimiter": "",
"ValueType": 0,
"Ignore": false,
"IsIndexer": false,
"IsCounter": false,
"StringFormat": null
}
]
你不能!
问题归结为来自 Embarcadero Delphi 的 TJsonObject class。在 Rest.Response.Adapter 单元中, json returned 被解析为一个 TJsonObject,然后在 CB_CollectFieldDefs 和 CB_CollectFieldData 中迭代对象中的所有 TJsonPairs。
第一个问题:CB_CollectionFieldDefs 将 ftString 硬编码为要添加到每个字段定义的数据集中的数据类型。因此,我 return 从我的 Web API 调用中编辑了字段类型,以消除猜测并手动构建字段定义。当 RestResponseDataSetAdapter 有字段定义时,单元正确跳过 CB_CollectionFieldDefs,这导致第二个问题。
Second problem:对象中的 Tjson 对没有正确解析布尔 json 值。到调用 CB_CollectFieldData 时,所有应该是变体类型的布尔值都是空字符串。所以我们得到异常 'Could not convert variant of type (UnicodeString) into type (Boolean)'.
遗憾的是,我不得不放弃这组有前途的组件,转而支持增强 Fabricio Colombo's excellent rest client api. Using the pattern in his GetAsDataSet logic, I created a number of post methods to post json (since the json creation from built in delphi units were incorrect, I substituted with SuperObject). I introduced PostJson and CreateDataset,这两个 return TClientDataSets。
function TResource.CreateDataset(data: string; table: string = ''; titles: string = ''): TClientDataSet;
var
vJson: ISuperObject;
begin
vJson := SuperObject.SO(data);
Result := TJsonToDataSetConverter.CreateDataSetMetadata(vJson, table, titles);
TJsonToDataSetConverter.ToDataSet(Result, vJson.O[table]);
end;
// which allows me to do:
ds := jsonrestclient1.Resource(url)
.ContentType(RestUtils.MediaType_Json)
.Accept(restutils.MediaType_Json)
.PostJson(json, 'Table', 'Titles');
// or
rs := jsonrestclient1.Resource(url)
.ContentType(RestUtils.MediaType_Json)
.Accept(restutils.MediaType_Json);
data:= rs.PostJson(Query) ;
vJson := SO(data);
fHasMore := vJson.B['HasMore'];
ds:= rs.CreateDataset(data, 'Table', 'Titles');
我在 Delphi XE5 中构建了一个 delphi 客户端示例,它利用了 Rest 库:
- TRestClient
- TRestRequest
- TRestResponse
- TRESTResponseDataSetAdapter
- TClientDataSet(和 TDataSource 绑定到 TDBGrid 和
TcxGridDBTableView)
全部由 ASP.net Web API 提供,该 Web API 根据来自 Delphi 的动态查询生成数据集。我可以成功地向客户端 运行 查询和 return 数据并呈现数据,但是布尔字段呈现为空白。
- 如何让 TClientDataSet 正确识别数据类型?
- 这是使用 TRESTResponseDataSetAdapter 的正确方法还是 TClientDataSet?
- 有没有人对这些组件有任何经验
编辑 令人惊讶的是,Embarcadero 的 TRestResponseDatasetAdapter 在内部执行此操作以创建字段:
procedure TCustomJSONDataSetAdapter.CB_CollectFieldDefs(const AJSONObject: TJSONObject);
var
LJSONPair: TJSONPair;
begin
for LJSONPair in AJSONObject do
begin
DoAddDataSetFieldDef(LJSONPair.JsonString.Value, ftString);
end;
end;
字段类型都硬编码为 ftString!
这是 returned json:
"Table": [
{
"Id": 34,
"Node": "Navision_ASN_1",
"FormatId": 2,
"Value": null,
"ParentID": null,
"DocumentOrder": 1,
"Combined": false,
"Delimiter": "",
"ValueType": 0,
"Ignore": false,
"IsIndexer": false,
"IsCounter": false,
"StringFormat": null
},
{
"Id": 35,
"Node": "MessageHeader",
"FormatId": 2,
"Value": null,
"ParentID": 34,
"DocumentOrder": 2,
"Combined": false,
"Delimiter": "",
"ValueType": 0,
"Ignore": false,
"IsIndexer": false,
"IsCounter": false,
"StringFormat": null
},
{
"Id": 52,
"Node": "Consignment",
"FormatId": 2,
"Value": null,
"ParentID": 34,
"DocumentOrder": 13,
"Combined": false,
"Delimiter": "",
"ValueType": 0,
"Ignore": false,
"IsIndexer": false,
"IsCounter": false,
"StringFormat": null
},
{
"Id": 53,
"Node": "Line",
"FormatId": 2,
"Value": null,
"ParentID": 52,
"DocumentOrder": 18,
"Combined": false,
"Delimiter": "",
"ValueType": 0,
"Ignore": false,
"IsIndexer": false,
"IsCounter": false,
"StringFormat": null
}
]
你不能!
问题归结为来自 Embarcadero Delphi 的 TJsonObject class。在 Rest.Response.Adapter 单元中, json returned 被解析为一个 TJsonObject,然后在 CB_CollectFieldDefs 和 CB_CollectFieldData 中迭代对象中的所有 TJsonPairs。
第一个问题:CB_CollectionFieldDefs 将 ftString 硬编码为要添加到每个字段定义的数据集中的数据类型。因此,我 return 从我的 Web API 调用中编辑了字段类型,以消除猜测并手动构建字段定义。当 RestResponseDataSetAdapter 有字段定义时,单元正确跳过 CB_CollectionFieldDefs,这导致第二个问题。
Second problem:对象中的 Tjson 对没有正确解析布尔 json 值。到调用 CB_CollectFieldData 时,所有应该是变体类型的布尔值都是空字符串。所以我们得到异常 'Could not convert variant of type (UnicodeString) into type (Boolean)'.
遗憾的是,我不得不放弃这组有前途的组件,转而支持增强 Fabricio Colombo's excellent rest client api. Using the pattern in his GetAsDataSet logic, I created a number of post methods to post json (since the json creation from built in delphi units were incorrect, I substituted with SuperObject). I introduced PostJson and CreateDataset,这两个 return TClientDataSets。
function TResource.CreateDataset(data: string; table: string = ''; titles: string = ''): TClientDataSet;
var
vJson: ISuperObject;
begin
vJson := SuperObject.SO(data);
Result := TJsonToDataSetConverter.CreateDataSetMetadata(vJson, table, titles);
TJsonToDataSetConverter.ToDataSet(Result, vJson.O[table]);
end;
// which allows me to do:
ds := jsonrestclient1.Resource(url)
.ContentType(RestUtils.MediaType_Json)
.Accept(restutils.MediaType_Json)
.PostJson(json, 'Table', 'Titles');
// or
rs := jsonrestclient1.Resource(url)
.ContentType(RestUtils.MediaType_Json)
.Accept(restutils.MediaType_Json);
data:= rs.PostJson(Query) ;
vJson := SO(data);
fHasMore := vJson.B['HasMore'];
ds:= rs.CreateDataset(data, 'Table', 'Titles');