Delphi:将JSON数组添加到JSON对象

问题描述

我正在使用Indy调用第三方API

var loRespJson: TMemoryStream;
IdHTTP1.GET(lsURL,loRespJson)

并返回一个JSON数组:

[
    {
        "Active": "1","SourceId": "215","SourceName": "MyVal1"
    },{
        "Active": "1","SourceId": "383","SourceName": "MyVal2"
    }
]

依次,我的函数创建一个新的JSON对象,添加其他信息以及响应,然后将其返回给调用程序。所需结果:

{
    "responseCode":"200","companyNo":"0268895","responseMessage": [
        {
            "Active": "1","SourceName": "MyVal1"
        },{
            "Active": "1","SourceName": "MyVal2"
        }
    ]
}

如何实现以上目标?如果我使用以下代码添加,它将在数组周围创建“”(引号),这在解析JSON时是一个大问题:

loJSon.AddPair(TJSONPair.Create('responseCode',IntToStr(idHttp1.ResponseCode)));
loJSon.AddPair(TJSONPair.Create('companyNo',CompanyNo));

if idHttp1.ResponseCode = 200 then
begin
  lsRespMsg := StreamToString(loRespJSon);
  liSuper := SO(lsRespMsg);
  loJSon.AddPair(TJSONPair.Create('responseMessage',liSuper.AsJSon()));
  …

我也尝试遍历JSON数组,但是该选项在每个数组项周围添加了“”。

{ create an json-array }
loJSA := TJsonArray.Create();
{ add array to object }
loJSP := TJSONPair.Create('responseMessage',loJSA);
loJSon.AddPair(loJSP);

if liSuper.IsType(stArray) then
begin
  for i := 0 to liSuper.AsArray.Length - 1 do
  begin
    loSubscription := liSuper.AsArray[i];
    loJSA.Add(loSubscription.AsJSon());
  end;
end;

任何帮助将不胜感激!谢谢。

解决方法

似乎您在尝试构建JSON新响应时使用了System.JSON单位中的loJSon: TJSONObject。然后,您使用来自SuperObject库的函数TIdHTTP解析了从SO()接收到的响应正文,该函数与System.JSON不太兼容。

到目前为止,这种方法很好,但是您应该坚持使用一个库。解析响应后,您添加了一对TJSONObject,其值为liSuper.AsJSon(),它是一个字符串。这就解释了包围数组的双引号。

仅使用System.JSON的正确解决方案如下所示:

uses
  System.SysUtils,System.JSON;

const
  ResponseMessageStr = '[{"Active":"1","SourceId":"215","SourceName":"MyVal1"},{"Active":"1","SourceId":"383","SourceName":"MyVal2"}]';
var
  ResponseJSON: TJSONObject;
begin
  ResponseJSON := TJSONObject.Create;
  try
    ResponseJSON.AddPair('responseCode','200');
    ResponseJSON.AddPair('companyNo','0268895');
    ResponseJSON.AddPair('responseMessage',TJSONObject.ParseJSONValue(ResponseMessageStr));
    Writeln(ResponseJSON.Format());
  finally
    ResponseJSON.Free;
  end;
end.

在上面的代码段中,我使用了TJSONObject.ParseJSONValue来解析响应消息并将其附加到生成的JSON对象中。尽管我的响应消息存储在字符串常量中,但是您可以轻松地调整解决方案以与TMemoryStreamTIdHTTP一起使用。检出TJSONObject.ParseJSONValue的所有不变量。

代码段产生输出:

{
    "responseCode": "200","companyNo": "0268895","responseMessage": [
        {
            "Active": "1","SourceId": "215","SourceName": "MyVal1"
        },{
            "Active": "1","SourceId": "383","SourceName": "MyVal2"
        }
    ]
}

还请注意,TJSONObject.AddPair有多个不变量,以方便您使用。另一点是,我使用了Format方法来漂亮地打印JSON对象的内容,但是您可能应该在生产中使用ToJSON

使用SuperObject库的解决方案会产生相同的结果:

uses
  System.SysUtils,SuperObject;

const
  ResponseMessageStr = '[{"Active":"1","SourceName":"MyVal2"}]';
var
  ResponseJSON: ISuperObject;
begin
  ResponseJSON := TSuperObject.Create;
  ResponseJSON.I['responseCode'] := 200;
  ResponseJSON.S['responseCode'] := '0268895';
  ResponseJSON.O['responseMessage'] := SO(ResponseMessageStr);
  Writeln(ResponseJSON.AsJSon(True));
  Readln;
end.