delphi 如何测试空JSON对象?

wkyowqbh  于 2023-03-18  发布在  其他
关注(0)|答案(1)|浏览(218)

设想

我在 Delphi 2009项目的各个地方使用了Andreas Hausladen的JsonDataObjects单元,现在我需要解析API调用远程服务器上的cpanel所返回的简单JSON。
大部分我都能做,但是在这种情况下返回的JSON看起来(至少在目前)有一个空对象{}(不是null),我希望得到一些帮助(a)测试空对象,(b)如果对象不空,则从对象中获取一些值。

数据

cpanel API文档here指出,返回的JSON具有以下格式,其中元数据为空。

{
   "apiversion": 3,
   "func": "add_host",
   "module": "Mysql",
   "result": {
      "data": null,
      "errors": null,
      "messages": null,
      "metadata": { },
      "status": 1,
      "warnings": null
   }
}

实际上文档是错的,我拿回来的数据是这样的形式,就是没有results对象,但是metadata对象还是空的,跟文档一样,不知道metadata对象不空的时候会是什么样子,文档没有说。

{                                   
   "data":"MyData",                    
   "errors":["The first error text"],  
   "warnings":null,                    
   "status":0,                         
   "messages":null,                    
   "metadata":{}                       
}

那些问题

1.如何测试对象MainObj['metadata']是否为空?它不是null,因为它包含{},所以If MainObj['metadata'].isnull ...返回false,代码进入else部分。
1.一旦我测试了它是否为空,当它没有名称时,我如何提取对象的数据(假定null)?

问题代码

这是一个小测试过程,演示了我解析这个数据时遇到的问题。大多数行都产生了预期的结果。问题出在对象MainObj['metadata']上,它在JSON中(当前)是空的。

procedure TForm1.btn1Click(Sender: TObject);
const 
  THEJSON =  ''
    +' {                                   '
    +' "data":"MyData",                    '
    +' "errors":["The first error text"],  '
    +' "warnings":null,                    '
    +' "status":0,                         '
    +' "messages":null,                    '
    +' "metadata":{}                       '
    +' }                                   ';    
var
  MainObj, MetaDataObject: TJsonObject;
  i : Integer;
begin
  MainObj := TJsonObject.Parse(THEJSON) as TJsonObject;
  try
    if MainObj['data'].IsNull then
      Memo2.Lines.Add('data = NULL')
    else
      Memo2.Lines.Add('data = ' + MainObj['data'].value);
    if MainObj['warnings'].IsNull then
      Memo2.Lines.Add('warnings = NULL')
    else
      Memo2.Lines.Add('warnings = ' + MainObj['warnings'].value);
    if MainObj['status'].IsNull then
      Memo2.Lines.Add('status = NULL')
    else
      Memo2.Lines.Add('status = ' + MainObj['status'].value);
    if MainObj['messages'].IsNull then
      Memo2.Lines.Add('messages = NULL')
    else
      Memo2.Lines.Add('messages = ' + MainObj['messages'].value);
    if MainObj['errors'].IsNull then
      Memo2.Lines.Add('errors = NULL')
    else
      for I := 0 to MainObj['errors'].count - 1 do
        Memo2.Lines.Add('Error' + IntToStr(i) + ' = ' + MainObj['errors'].items[i]) ;
    
    if MainObj['metadata'].isnull then
      Memo2.Lines.Add('metadata = No object')
    else
    begin
      //this is where it goes pear shaped!
      MetaDataObject := TJsonObject.Parse(MainObj['metadata']) as TJsonObject;   //cannot cast object to string???
      try
        Memo2.Lines.Add('metadata text is ' + MetaDataObject.ToString);
        if MetaDataObject['????].isnull then   / if MetaDataObject['????] is empty then   //what goes here?
          Memo2.Lines.Add('metadata = NULL')
        else                    '
          Memo2.Lines.Add('metadata = ' + MetaDataObject.Value);
      finally
        MetaDataObject.Free;
      end;
    end;
  finally
    MainObj.Free;
  end;
end;

预期成果

data = MyData
warnings = NULL
status = 0
messages = NULL
Error0 = The first error text

接着是

metadata text is {}
metadata = NULL

或者,如果其中有数据,则后跟

metadata text is {"meta_1":"mymeta"}
metadata = mymeta

实际结果

data = MyData
warnings = NULL
status = 0
messages = NULL
Error0 = The first error text

后跟运行时错误“无法将对象强制转换为字符串”。
"我所尝试的"

if not Assigned(MetaDataObject) then ...
if not Assigned(MainObj['metadata']) then ...
if Assigned (TJsonObject(MainObj['metadata'])) then
  MetaDataObject := TJsonObject.Parse(MainObj['metadata']) as TJsonObject;

我所看到的地方

JSON specification for empty objects
Empty JSON Object check

tcbh2hod

tcbh2hod1#

您已经知道如何从JSON对象访问子值。
当JSON对象为非空但没有子值(即为空)时,TJsonObject.Count属性将为0。因此,首先检查所需的值是否为null,如果不是,则将该值作为TJsonObject访问,并检查其Count是否为0,然后相应地进行操作。
例如:

if MainObj.IsNull('metadata') then
  Memo2.Lines.Add('metadata = No object')
else
begin
  MetaDataObject := MainObj.O['metadata'];
  if MetaDataObject.Count = 0 then
    Memo2.Lines.Add('metadata = empty')
  else
    Memo2.Lines.Add('metadata text is ' + MetaDataObject.ToString);
end;

相关问题