JSON空数组

Sam*_*m M 9 delphi delphi-xe2

我试图解析从REST Web服务返回的一些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;
Run Code Online (Sandbox Code Playgroud)

有时,此JSON数据中的phone_numbers数组为空.在来自Web服务调用的流对象中,它看起来像这样:

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

]
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这会导致ParseJSONValue返回nil值.

但是,如果我在我的测试txt文件中将空phone_numbers数组更改为:

{
    "Contact Information Service": {
        "response": {
            "phone_numbers": []
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它工作正常(即返回一个TJSONObject).不同之处在于空数组中的空格.由于某种原因,空数组中具有空格的第一个JSON响应导致ParseJSONValue返回nil.它工作正常,方括号之间没有空格.

我的JSON解析出了什么问题?在调用ParseJSONValue之前是否需要进行某种预解析?

RRU*_*RUZ 10

这个问题并不包括Delphi JSON实现(DBXJSON),我使用了一些具有相同限制的JSON PHP解析器.

现在,因为由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.
Run Code Online (Sandbox Code Playgroud)


Mas*_*ler 7

看看TJsonObject.ParseArray.你会发现这个:

while ValueExpected or (Br.PeekByte <> Ord(']')) do
begin
  ConsumeWhitespaces(Br);
  Pos := ParseValue(Br, JsonArray);
  if Pos <= 0 then
    Exit(Pos);
Run Code Online (Sandbox Code Playgroud)

所以在数组的顶部(在它读取开括号之后),如果下一个字符不是一个近括号,则吃空格然后尝试读取有效的JSON值.关闭括号不是有效的JSON值,因此此时它会失效.

这似乎是有效的JSON,(我可以让我的浏览器接受它作为一个有效的JavaScript对象),所以这应该被认为是DBXJSON库中的一个错误.您可能需要预先解析它,使用不同的JSON库(Delphi有一些)或找到一种方法来确保发送给您的信息不包含此模式.

无论哪种方式,您都应该将此报告给QC作为错误.