gpt4 book ai didi

json - 使用 Embarcadero 代码示例通过 TJSONObject 解析有效 JSON 失败并出现异常

转载 作者:行者123 更新时间:2023-12-03 14:39:34 30 4
gpt4 key购买 nike

以下是 Embarcadero 帮助中的示例代码 ( http://docwiki.embarcadero.com/RADStudio/Rio/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;

该方法失败,并在 as 行上进行类无效类型转换!!

使用解析:

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;

在 Embarcadero 示例中,输入 JSON 在代码中声明为字符串:

  const
GJSONString =
'{' +
' "name": {'+
' "A JSON Object": {' +
' "id": "1"' +
' },' +
' "Another JSON Object": {' +
' "id": "2"' +
' }' +
' },' +
' "totalobjects": "2"' +
'}';

我正在处理的 JSON 来自 BetFair。它是有效的(用 http://jsonformatter.curiousconcept.com/http://www.freeformatter.com/json-validator.htmlhttp://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": {
}
}]

我没有将其声明为字符串,而是从文件中读取它:

TFile.ReadAllText(aFileName);

文件读取成功。

这是导致问题的代码。我已按照 Embarcadero 文档的建议使用了方法 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;

这种没有足够的 IDE 和语言文档或者文档不完整或不充分的情况 - 是一种严重的时间浪费,并且给我完成工作带来了问题。我需要使用语言和库来解决问题,而不是用它们来解决问题,或者更重要的是用不充分、模糊且难以找到的文档来解决问题。

最佳答案

如果解析失败,

TJSONObject.ParseJSONValue() 返回一个 nil 指针。 Embarcadero 的示例不检查该条件。如果解析失败,则会导致 as 运算符引发“无效类型转换”错误。

如果解析失败,

TJSONObject.Parse() 返回 -1。 Embarcadero 的示例不会检查该条件。

因为 TJSONObject 解析字节,而不是字符,所以我建议您不要使用 TFile.ReadAllText(),它将读取字节并使用 将它们解码为 UTF-16 >TEncoding.Default 如果文件没有 BOM。在您的特定示例中,这不是问题,因为您的 JSON 仅包含 ASCII 字符。但如果使用非 ASCII Unicode 字符,这可能会成为一个问题。 JSON 默认使用 UTF-8(这就是为什么 TJSONObject.ParseJSONValue()IsUTF8 参数默认为 true)。

无论如何,您的代码与您显示的 JSON 数据的结构不匹配。您的 JSON 数据是一个对象数组,因此解析的第一个项目将是 TJSONArray,而不是 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;

或者简单地说:

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;

如果您使用 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;

或者简单地说:

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;

更新:如果您尝试 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;

关于json - 使用 Embarcadero 代码示例通过 TJSONObject 解析有效 JSON 失败并出现异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24815625/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com