Bru*_*ong 10 delphi parsing json
以下是Embarcadero帮助的示例代码(http://docwiki.embarcadero.com/RADStudio/XE5/en/JSON):
您可以使用以下代码片段之一将JSON字符串表示形式转换为JSON.
使用ParseJSONValue:
procedure ConsumeJsonString;
var
LJSONObject: TJSONObject;
begin
LJSONObject := nil;
try
{ convert String to JSON }
LJSONObject := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(GJSONString), 0) as TJSONObject;
{ output the JSON to console as String }
Writeln(LJSONObject.ToString);
finally
LJSONObject.Free;
end;
Run Code Online (Sandbox Code Playgroud)
该方法失败,并在as行上抛出类无效类型!
使用Parse:
procedure ConsumeJsonBytes;
var
LJSONObject: TJSONObject;
begin
LJSONObject := nil;
try
LJSONObject := TJsonObject.Create;
{ convert String to JSON }
LJSONObject.Parse(BytesOf(GJSONString), 0);
{ output the JSON to console as String }
Writeln(LJSONObject.ToString);
finally
LJSONObject.Free;
end;
end;
Run Code Online (Sandbox Code Playgroud)
在Embarcadero示例中,输入JSON在代码中声明为字符串:
const
GJSONString =
'{' +
' "name": {'+
' "A JSON Object": {' +
' "id": "1"' +
' },' +
' "Another JSON Object": {' +
' "id": "2"' +
' }' +
' },' +
' "totalobjects": "2"' +
'}';
Run Code Online (Sandbox Code Playgroud)
我正在处理的JSON来自BetFair.它是有效的(通过http://jsonformatter.curiousconcept.com/和http://www.freeformatter.com/json-validator.html和http://jsonlint.com/验证):
[{
"caption": "Get the number of soccer markets",
"methodName": "SportsAPING/v1.0/listEventTypes",
"params": {
"filter": {
"eventTypeIds": [
1
]
}
}
},
{
"caption": "Get the next horse race in the UK",
"methodName": "SportsAPING/v1.0/listMarketCatalogue",
"params": {
"filter": {
"eventTypeIds": [
7
],
"marketCountries": [
"GB"
],
"marketTypeCodes": [
"WIN"
],
"marketStartTime": {
"from": "2013-04-11T11:03:36Z"
}
},
"sort": "FIRST_TO_START",
"maxResults": "1",
"marketProjection": [
"COMPETITION",
"EVENT",
"EVENT_TYPE",
"MARKET_DESCRIPTION",
"RUNNER_DESCRIPTION"
]
}
},
{
"caption": "Get the 2 best prices, rolled up to £10 for the London Mayor Election 2016",
"methodName": "SportsAPING/v1.0/listMarketBook",
"params": {
"marketIds": [
"1.107728324"
],
"priceProjection": {
"priceData": [
"EX_BEST_OFFERS"
],
"exBestOffersOverrides": {
"bestPricesDepth": "2",
"rollupModel": "STAKE",
"rollupLimit": "10"
}
}
}
},
{
"caption": "Get my current unmatched bets",
"methodName": "SportsAPING/v1.0/listCurrentOrders",
"params": {
"orderProjection": "EXECUTABLE"
}
},
{
"caption": "Get my application keys",
"methodName": "AccountAPING/v1.0/getDeveloperAppKeys",
"params": {
}
}]
Run Code Online (Sandbox Code Playgroud)
我没有将此声明为字符串,而是从文件中读取它:
TFile.ReadAllText(aFileName);
Run Code Online (Sandbox Code Playgroud)
文件读取成功.
这是导致问题的代码.我按照Embarcadero docs的建议使用了方法2,如上所述.那失败了.为了调试目的,我将方法拆分为更多变量.
根据Embarcadero文档,如果解析因任何原因失败,则vParseResult将为负值.它不是.但是,即使解析成功(尝试后的第二行)导致异常,vJSONPair也会结束为零:
procedure TfMain.loadScenarioData(aFilename: string);
var
vJSONString: string;
vJSONScenario: TJSONObject;
vJSONPair: TJSONPair;
vJSONScenarioEntry: TJSONValue;
vJSONScenarioValue: string;
I: Int16;
vParseResult: Integer;
begin
vJSONString := TFile.ReadAllText(aFileName);
vJSONScenario := nil;
try
vJSONScenario := TJSONObject.Create;
vParseResult := vJSONScenario.Parse(BytesOf(vJSONString),0);
if vParseResult >= 0 then
begin
//BetFair Specific 'caption' key
vJSONPair := vJSONScenario.Get('caption');
vJSONScenarioEntry := vJSONPair.JsonValue;
vJSONScenarioValue := vJSONScenarioEntry.Value;
cbScenario.Items.Add(vJSONScenarioValue);
end;
finally
vJSONScenario.Free;
end;
end;
Run Code Online (Sandbox Code Playgroud)
这种事情那里没有IDE和语言或者文档是不完整的或足够的适当的文件 - 是时间的可怕的浪费,并给了我完成工作中的问题.我需要使用语言和库来解决问题,而不是用不充分,模糊和难以找到的文档解决问题或更多问题.
Rem*_*eau 22
TJSONObject.ParseJSONValue()
nil
如果解析失败,则返回指针.Embarcadero的例子没有检查那个条件.如果解析失败,那将解释as
运营商引发的"无效类型转换"错误.
TJSONObject.Parse()
如果解析失败,则返回-1.Embarcadero的例子没有检查那个条件.
因为TJSONObject
解析字节而不是字符,我建议你不要使用TFile.ReadAllText()
,TEncoding.Default
如果文件没有BOM ,它将读取字节并将它们解码为UTF-16 .在您的特定示例中,这不是问题,因为您的JSON仅包含ASCII字符.但如果使用非ASCII Unicode字符,则可能会出现问题.JSON默认使用UTF-8(这就是默认情况下IsUTF8
参数TJSONObject.ParseJSONValue()
为true的原因).
在任何情况下,您的代码都与您显示的JSON数据的结构不匹配.您的JSON数据是一个对象数组,因此解析的第一个项目将是a TJSONArray
,而不是a TJSONObject
.如果你使用TSJONObject.ParseJSONValue()
,它将返回一个TJSONValue
可以类型转换为TJSONArray
:
procedure TfMain.loadScenarioData(aFilename: string);
var
vJSONBytes: TBytes;
vJSONScenario: TJSONValue;
vJSONArray: TJSONArray;
vJSONValue: TJSONValue;
vJSONObject: TJSONObject;
vJSONPair: TJSONPair;
vJSONScenarioEntry: TJSONValue;
vJSONScenarioValue: TJSONString;
begin
vJSONBytes := TFile.ReadAllBytes(aFileName);
vJSONScenario := TJSONObject.ParseJSONValue(vJSONBytes, 0);
if vJSONScenario <> nil then
try
//BetFair Specific 'caption' key
vJSONArray := vJSONScenario as TJSONArray;
for vJSONValue in vJSONArray do
begin
vJSONObject := vJSONValue as TJSONObject;
vJSONPair := vJSONObject.Get('caption');
vJSONScenarioEntry := vJSONPair.JsonValue;
vJSONScenarioValue := vJSONScenarioEntry as TJSONString;
cbScenario.Items.Add(vJSONScenarioValue.Value);
end;
finally
vJSONScenario.Free;
end;
end;
Run Code Online (Sandbox Code Playgroud)
或者干脆:
procedure TfMain.loadScenarioData(aFilename: string);
var
vJSONScenario: TJSONValue;
vJSONValue: TJSONValue;
begin
vJSONScenario := TJSONObject.ParseJSONValue(TFile.ReadAllBytes(aFileName), 0);
if vJSONScenario <> nil then
try
//BetFair Specific 'caption' key
for vJSONValue in vJSONScenario as TJSONArray do
begin
cbScenario.Items.Add(((vJSONValue as TJSONObject).Get('caption').JsonValue as TJSONString).Value);
end;
finally
vJSONScenario.Free;
end;
end;
Run Code Online (Sandbox Code Playgroud)
如果你TJSONObject.Parse()
改为使用,那么TJSONArray
它将被添加为你正在调用的对象的子节点Parse()
,但它是一个未命名的数组,所以你必须通过索引检索数组:
procedure TfMain.loadScenarioData(aFilename: string);
var
vJSONBytes: TBytes;
vJSONScenario: TJSONObject;
vJSONArray: TJSONArray;
vJSONValue: TJSONValue;
vJSONObject: TJSONObject;
vJSONPair: TJSONPair;
vJSONScenarioEntry: TJSONString;
vJSONScenarioValue: string;
vParseResult: Integer;
begin
vJSONBytes := TFile.ReadAllBytes(aFileName);
vJSONScenario := TJSONObject.Create;
try
vParseResult := vJSONScenario.Parse(vJSONBytes, 0);
if vParseResult >= 0 then
begin
//BetFair Specific 'caption' key
vJSONArray := vJSONScenario.Get(0) as TJSONArray;
for vJSONValue in vJSONArray do
begin
vJSONObject := vJSONValue as TJSONObject;
vJSONPair := vJSONObject.Get('caption');
vJSONScenarioEntry := vJSONPair.JsonString;
vJSONScenarioValue := vJSONScenarioEntry.Value;
cbScenario.Items.Add(vJSONScenarioValue);
end;
end;
finally
vJSONScenario.Free;
end;
end;
Run Code Online (Sandbox Code Playgroud)
或者干脆:
procedure TfMain.loadScenarioData(aFilename: string);
var
vJSONScenario: TJSONObject;
vJSONValue: TJSONValue;
vParseResult: Integer;
begin
vJSONScenario := TJSONObject.Create;
try
vParseResult := vJSONScenario.Parse(TFile.ReadAllBytes(aFileName), 0);
if vParseResult >= 0 then
begin
//BetFair Specific 'caption' key
for vJSONValue in vJSONScenario.Get(0) as TJSONArray do
begin
cbScenario.Items.Add(((vJSONValue as TJSONObject).Get('caption').JsonValue as TJSONString).Value);
end;
end;
finally
vJSONScenario.Free;
end;
end;
Run Code Online (Sandbox Code Playgroud)
更新:如果您尝试使用SuperObject,代码会更简单一些,例如:
procedure TfMain.loadScenarioData(aFilename: string);
var
vJSONScenario: ISuperObject;
vJSONArray: ISuperObject;
vJSONObject: ISuperObject;
vJSONScenarioValue: string;
I: Integer;
begin
vJSONScenario := TSuperObject.ParseFile(aFileName);
//BetFair Specific 'caption' key
vJSONArray := vJSONScenario.AsArray;
for I := 0 to vJSONArray.Length-1 do
begin
vJSONObject := vJSONArray[I].AsObject;
vJSONScenarioValue := vJSONObject.S['caption'];
cbScenario.Items.Add(vJSONScenarioValue);
end;
end;
Run Code Online (Sandbox Code Playgroud)