使用 Delphi 解析可为 null 的 TJSONObject
Parsing nullable TJSONObject with Delphi
我正在使用 Delphi XE3。我有一个 JSON 流,其中对象可以为空。即我可以收到:
"user":null
或
"user":{"userName":"Pep","email":"pep@whosebug.com"}
我想区分这两种情况,我尝试使用以下代码:
var
jUserObject: TJSONObject;
jUserObject := TJSONObject(Get('user').JsonValue);
if (jUserObject.Null)
then begin
FUser := nil;
end else begin
FUser := TUser.Create;
with FUser, jUserObject do begin
FEmail := TJSONString(Get('email').JsonValue).Value;
FUserName := TJSONString(Get('userName').JsonValue).Value;
end;
end;
如果我在 if (jUserObject.Null) then begin
行中放置一个断点并将鼠标悬停在 jUserObject.Null
上,它会显示 jUserObject.Null = True
if "user":null
并且显示 jUserObject.Null = False
if "user":{"userName":"Pep","email":"pep@whosebug.com"}
但是,如果我使用调试器进入该行,jUserObject.Null 调用以下 XE3 库代码:
function TJSONAncestor.IsNull: Boolean;
begin
Result := False;
end;
所以我的 if
句子总是得到 False
,即使 "user":null
.
我想我总是有解决方法来捕获执行 "user":null
和 Get('email').JsonValue
时引发的异常,以便区分值是否为 null,但这似乎不是好优雅。
如何检测 JSON 对象在 JSON 流中是否具有空值?
您犯了将 JSON 对象与 Delphi 对象混淆的常见错误。 TJSONObject
class 仅表示 JSON 个对象,它们永远不会为空,因为 null
不同于 {...}
。 TJSONObject
不是所有 JSON 值的祖先,就像您的代码假设的那样。 TJSONValue
是。
在您知道它是一个对象之前,不要将您的 "user" 值强制转换为 TJSONObject
。首先检查 Null
属性, 然后 类型转换。
Get()
return一个TJSONPair
。当您有 "user":null
时,TJSONPair.JsonValue
属性 将 return 一个 TJSONNull
对象,而不是 TJSONObject
对象。您的代码没有考虑到这种可能性。它假定 JsonValue
始终是 TJSONObject
并且不验证类型转换。
有两种方法可以解决这个问题。
TJSONPair
有自己的 Null
属性 指定其 JsonValue
是否为空值:
var
JUser: TJSONPair;
jUserObject: TJSONObject;
jUser := Get('user');
if jUser.Null then begin
FUser := nil;
end else begin
// use the 'as' operator for type validation in
// case the value is something other than an object...
jUserObject := jUser.JsonValue as TJSONObject;
...
end;
使用 is
运算符在转换之前测试 JsonValue
的 class 类型:
var
JUser: TJSONPair;
jUserObject: TJSONObject;
jUser := Get('user');
if jUser.JsonValue is TJSONNull then begin
FUser := nil;
end
else if jUser.JsonValue is TJSONObject then begin
jUserObject := TJSONObject(jUser.JsonValue);
...
end else begin
// the value is something other than an object...
end;
我正在使用 Delphi XE3。我有一个 JSON 流,其中对象可以为空。即我可以收到:
"user":null
或
"user":{"userName":"Pep","email":"pep@whosebug.com"}
我想区分这两种情况,我尝试使用以下代码:
var
jUserObject: TJSONObject;
jUserObject := TJSONObject(Get('user').JsonValue);
if (jUserObject.Null)
then begin
FUser := nil;
end else begin
FUser := TUser.Create;
with FUser, jUserObject do begin
FEmail := TJSONString(Get('email').JsonValue).Value;
FUserName := TJSONString(Get('userName').JsonValue).Value;
end;
end;
如果我在 if (jUserObject.Null) then begin
行中放置一个断点并将鼠标悬停在 jUserObject.Null
上,它会显示 jUserObject.Null = True
if "user":null
并且显示 jUserObject.Null = False
if "user":{"userName":"Pep","email":"pep@whosebug.com"}
但是,如果我使用调试器进入该行,jUserObject.Null 调用以下 XE3 库代码:
function TJSONAncestor.IsNull: Boolean;
begin
Result := False;
end;
所以我的 if
句子总是得到 False
,即使 "user":null
.
我想我总是有解决方法来捕获执行 "user":null
和 Get('email').JsonValue
时引发的异常,以便区分值是否为 null,但这似乎不是好优雅。
如何检测 JSON 对象在 JSON 流中是否具有空值?
您犯了将 JSON 对象与 Delphi 对象混淆的常见错误。 TJSONObject
class 仅表示 JSON 个对象,它们永远不会为空,因为 null
不同于 {...}
。 TJSONObject
不是所有 JSON 值的祖先,就像您的代码假设的那样。 TJSONValue
是。
在您知道它是一个对象之前,不要将您的 "user" 值强制转换为 TJSONObject
。首先检查 Null
属性, 然后 类型转换。
Get()
return一个TJSONPair
。当您有 "user":null
时,TJSONPair.JsonValue
属性 将 return 一个 TJSONNull
对象,而不是 TJSONObject
对象。您的代码没有考虑到这种可能性。它假定 JsonValue
始终是 TJSONObject
并且不验证类型转换。
有两种方法可以解决这个问题。
TJSONPair
有自己的Null
属性 指定其JsonValue
是否为空值:var JUser: TJSONPair; jUserObject: TJSONObject; jUser := Get('user'); if jUser.Null then begin FUser := nil; end else begin // use the 'as' operator for type validation in // case the value is something other than an object... jUserObject := jUser.JsonValue as TJSONObject; ... end;
使用
is
运算符在转换之前测试JsonValue
的 class 类型:var JUser: TJSONPair; jUserObject: TJSONObject; jUser := Get('user'); if jUser.JsonValue is TJSONNull then begin FUser := nil; end else if jUser.JsonValue is TJSONObject then begin jUserObject := TJSONObject(jUser.JsonValue); ... end else begin // the value is something other than an object... end;