我使用的是Delphi XE3。我有一个JSON流,其中一个对象可以为null。也就是说,我可以收到:
"user":null
或
"user":{"userName":"Pep","email":"pep@stackoverflow.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
它会显示"user":null
,如果jUserObject.Null = False
则显示"user":{"userName":"Pep","email":"pep@stackoverflow.com"}
}}
但是,如果我使用调试器进入该行,jUserObject.Null将调用以下XE3库代码:
function TJSONAncestor.IsNull: Boolean;
begin
Result := False;
end;
即使False
,我的if
句也总是"user":null
。
我想我总是有一个解决方法,即捕获在执行"user":null
和Get('email').JsonValue
时引发的异常,以便区分值是否为null,但这看起来并不那么优雅
如何判断JSON对象在JSON流中是否具有空值?
答案 0 :(得分:5)
Get()
返回TJSONPair
。当您拥有"user":null
时,TJSONPair.JsonValue
属性将返回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
的类类型:
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;
答案 1 :(得分:3)
您犯了将JSON对象与Delphi对象混淆的常见错误。 TJSONObject
类仅表示JSON对象,它们永远不会为空,因为null
与{...}
不同。 TJSONObject
不是所有JSON值的祖先,就像您的代码所假设的那样。 TJSONValue
是。
不要输入你的用户"价值为TJSONObject
,直到您知道它为对象。首先检查Null
属性,然后输入类型。