lazarus - TJSONData 路径存在
lazarus - TJSONData path exists
我正在尝试使用 JSON,但我的问题是我找不到任何方法来检查路径是否存在或获取路径列表。
例如,我的应用程序从服务器收到此 JSON:
{
"ok": true,
"result":[
{
"id": 12,
"first_name": "David",
"username": "Fake"
},
{
"id": 13,
"first_name": "John",
"username": "sample",
"message":"test msg"
}
,{
"id": 13,
"first_name": "David",
"username": "Fake",
"text":"test txet"
}
]
}
但是数据不相等,比如John
有一个message
但是David
没有。
注意:如果我尝试为每个人阅读 message
,我会在代码中遇到异常。
这是我的代码:
for i := 0 to jsonDoc.findpath('result').Count - 1 do
begin
// jsonDoc.findpath('result').Items[i].WHAT IS NEED FOR CHECK ??
Result[i].text := jsonDoc.findpath('result').Items[i].FindPath('message').AsString; // exception
end;
请指导我查找路径列表或检查路径是否存在。
我使用 my own JSON implementation,所以不熟悉 Lazarus JSON 的具体实现,但是从您发布的代码来看,FindPath('message')
returns NIL 如果指定的路径不存在。
因此,与其无条件地使用 FindPath()
的 return,不如将结果分配给适当类型的某个中间变量,并在尝试之前测试 NIL访问任何成员:
var
msg: T??;
//...
msg := jsonDoc.findpath('result').Items[i].FindPath('message');
if Assigned(msg) then
Result[i].text := msg.AsString
else
Result[i].text := ''; // If necessary
//...
为了比较,我的 JSON 库使用 OptXXX 函数来读取对象上可能不存在的值(Opt ==> 可选),因此等效于使用我的实现是这样的:
var
jsonResults: TJSONArray;
//..
jsonResults := jsonDoc['result'].AsArray;
for i := 0 to Pred(jsonResults.Count) do
result[i].Text := jsonResults[i].AsObject.OptString('message');
但是,我还没有使用 FPC/Lazarus 测试我的库,因此此代码仅供 interest/Delphi 开发人员使用,不作为建议(请参阅上面的初始代码片段)。
首先,您对 findPath('result')
的使用非常低效。您应该 调用它一次 并将返回的对象保存到局部变量。
其次,FindPath()
returns nil
如果找不到指定的路径,但您没有检查该条件,这就是为什么当 message
丢失。
试试这个:
var
jsonDoc, r: TJSONData;
msg: TJSONData;
I: Integer;
begin
jsonDoc := ...;
r := jsonDoc.findpath('result');
if r <> nil then
begin
for i := 0 to res.Count - 1 do
begin
msg := res.Items[i].FindPath('message');
if msg <> nil then
Result[i].text := msg.AsString
else
Result[i].text := '';
end;
end;
end;
请阅读 Lazarus 的文档了解更多详情:
我正在尝试使用 JSON,但我的问题是我找不到任何方法来检查路径是否存在或获取路径列表。
例如,我的应用程序从服务器收到此 JSON:
{
"ok": true,
"result":[
{
"id": 12,
"first_name": "David",
"username": "Fake"
},
{
"id": 13,
"first_name": "John",
"username": "sample",
"message":"test msg"
}
,{
"id": 13,
"first_name": "David",
"username": "Fake",
"text":"test txet"
}
]
}
但是数据不相等,比如John
有一个message
但是David
没有。
注意:如果我尝试为每个人阅读 message
,我会在代码中遇到异常。
这是我的代码:
for i := 0 to jsonDoc.findpath('result').Count - 1 do
begin
// jsonDoc.findpath('result').Items[i].WHAT IS NEED FOR CHECK ??
Result[i].text := jsonDoc.findpath('result').Items[i].FindPath('message').AsString; // exception
end;
请指导我查找路径列表或检查路径是否存在。
我使用 my own JSON implementation,所以不熟悉 Lazarus JSON 的具体实现,但是从您发布的代码来看,FindPath('message')
returns NIL 如果指定的路径不存在。
因此,与其无条件地使用 FindPath()
的 return,不如将结果分配给适当类型的某个中间变量,并在尝试之前测试 NIL访问任何成员:
var
msg: T??;
//...
msg := jsonDoc.findpath('result').Items[i].FindPath('message');
if Assigned(msg) then
Result[i].text := msg.AsString
else
Result[i].text := ''; // If necessary
//...
为了比较,我的 JSON 库使用 OptXXX 函数来读取对象上可能不存在的值(Opt ==> 可选),因此等效于使用我的实现是这样的:
var
jsonResults: TJSONArray;
//..
jsonResults := jsonDoc['result'].AsArray;
for i := 0 to Pred(jsonResults.Count) do
result[i].Text := jsonResults[i].AsObject.OptString('message');
但是,我还没有使用 FPC/Lazarus 测试我的库,因此此代码仅供 interest/Delphi 开发人员使用,不作为建议(请参阅上面的初始代码片段)。
首先,您对 findPath('result')
的使用非常低效。您应该 调用它一次 并将返回的对象保存到局部变量。
其次,FindPath()
returns nil
如果找不到指定的路径,但您没有检查该条件,这就是为什么当 message
丢失。
试试这个:
var
jsonDoc, r: TJSONData;
msg: TJSONData;
I: Integer;
begin
jsonDoc := ...;
r := jsonDoc.findpath('result');
if r <> nil then
begin
for i := 0 to res.Count - 1 do
begin
msg := res.Items[i].FindPath('message');
if msg <> nil then
Result[i].text := msg.AsString
else
Result[i].text := '';
end;
end;
end;
请阅读 Lazarus 的文档了解更多详情: