Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi JSON空数组_Delphi_Delphi Xe2 - Fatal编程技术网

Delphi JSON空数组

Delphi JSON空数组,delphi,delphi-xe2,Delphi,Delphi Xe2,我试图解析从RESTWeb服务返回的一些JSON。get()调用返回的是TStringStream。我使用dbxjson处理数据。为了更容易在这里演示,我创建了一个测试项目,它在不调用web服务的情况下复制错误(使用文本文件作为web服务输出)。代码如下: var SL : TStringStream; LJsonObj : TJSONObject; begin SL := TStringStream.Create; try SL.LoadFromFile('output.t

我试图解析从RESTWeb服务返回的一些JSON。get()调用返回的是TStringStream。我使用dbxjson处理数据。为了更容易在这里演示,我创建了一个测试项目,它在不调用web服务的情况下复制错误(使用文本文件作为web服务输出)。代码如下:

var SL : TStringStream;
  LJsonObj : TJSONObject;
begin
  SL := TStringStream.Create;
  try
    SL.LoadFromFile('output.txt');
    LJsonObj := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(SL.DataString), 0) as TJSONObject;
  finally
    SL.Free;
  end;
end;
有时,此JSON数据中的电话号码数组为空。在来自web服务调用的流对象中,它如下所示:

{
    "Contact Information Service": {
        "response": {
            "phone_numbers": [

]
        }
    }
}
这将导致ParseJSONValue返回一个nil值

但是,如果我在测试txt文件中将空电话号码数组更改为:

{
    "Contact Information Service": {
        "response": {
            "phone_numbers": []
        }
    }
}
它工作正常(即返回TJSONObject)。区别在于空数组中的空格。出于某种原因,第一个JSON响应在空数组中带有空格,导致ParseJSONValue返回nil。它工作正常,方括号之间没有空格


我的JSON解析有什么错?在调用ParseJSONValue之前,我需要进行某种预解析吗?

看看
TJsonObject.ParseArray
。你会发现:

while ValueExpected or (Br.PeekByte <> Ord(']')) do
begin
  ConsumeWhitespaces(Br);
  Pos := ParseValue(Br, JsonArray);
  if Pos <= 0 then
    Exit(Pos);
whilevalueexpected或(Br.peek字节Ord(']')do
开始
用户空白(Br);
Pos:=解析值(Br,JsonArray);

如果Pos这个问题不是Delphi JSON实现(DBXJSON)所独有的,那么我使用的一些JSON PHP解析器也有同样的限制

现在,由于JSON解析器会(并且必须)忽略双引号字符串文本之外的所有空格,因此可以安全地删除这些空格,因此一种可能的解决方法是在解析JSON字符串之前缩小JSON字符串

试试这个示例,它使用正则表达式从字符串中删除多余的空格

{$APPTYPE CONSOLE}

{$R *.res}


uses
  System.RegularExpressions,
  System.Classes,
  System.SysUtils,
  Data.DBXJSON;

const
JsonString=
'{'+
'    "Contact Information Service": {'+
'        "response": {'+
'            "phone_numbers": [        ]'+
'        }'+
'    }'+
'}';

function JsonMinify(const S: string): string;
begin
 Result:=TRegEx.Replace(S,'("(?:[^"\\]|\\.)*")|\s+', '$1');
end;

procedure TestJSon;
var
  s : string;
  SL : TStringStream;
  LJsonObj : TJSONObject;
begin
  SL := TStringStream.Create;
  try
    s:=JsonMinify(JsonString);
    SL.WriteString(s);
    LJsonObj := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(SL.DataString), 0) as TJSONObject;
    Writeln(LJsonObj.Size);
  finally
    SL.Free;
  end;
end;

begin
 try
    TestJSon;
 except
    on E:Exception do
        Writeln(E.Classname, ':', E.Message);
 end;
 Writeln('Press Enter to exit');
 Readln;
end.

看起来这很可能是TJSONByteReader实现中的一个bug,但坦率地说,试图弄清楚解析代码的意义使我们无法一目了然。从经验上看,证据相当清楚。幸运的是,我自己的TJSONObject阅读器可以很好地处理此类情况。该发表了吗?:)@德尔蒂斯:真的吗?我在研究这个问题的过程中进行了跟踪,我发现理解解析代码并没有那么困难。我认为解析器写得很糟糕——如果它有一个合适的词法分析器,而不是将词法分析与解析混合在一起,那么这个问题就完全可以避免——但要理解发生了什么并不难……如果你发现PeekByte()很容易理解,那么你就必须用十六进制作梦。:)当我发布我的JSON代码时,你会看到我认为可读的(我敢说可维护的)代码和UM,dxxJSON之间的区别。因为我没有解决我正在经历的问题,所以当我遇到PekByTee()时,我放弃了,作为一个明确的“这里是龙”的红旗。所以我从来没有真正了解过ParseArray(),正如您在下面提到的,它非常清楚,而且明显有缺陷。(Parse..()方法在TJSONObject中到底在做什么?)@Deltics:你的意思是你不会做梦?我想我已经习惯了。我甚至看不到代码了。我只看到金发、黑发、红发……;)但是,即使正确实现JSON规范(您已经在XE2中购买了该功能)是一个明显而简单的失败,您也无法在XE2中修复它。你忘了提那部分。