【问题标题】:Delphi: Adding JSON Array to JSON ObjectDelphi:将 JSON 数组添加到 JSON 对象
【发布时间】:2020-08-24 13:09:11
【问题描述】:

我正在使用 Indy 调用第 3 方 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",
            "SourceId": "215",
            "SourceName": "MyVal1"
        },
        {
            "Active": "1",
            "SourceId": "383",
            "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;

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

【问题讨论】:

  • 您正在混合使用 2 个不同的库来处理 JSON - SuperObjectSystem.JSON。选择一个作为一个好的开始。

标签: json delphi delphi-2010


【解决方案1】:

您似乎在尝试构建 JSON 新响应时使用了单元 System.JSON 中的 loJSon: TJSONObject。然后,您使用 SuperObject 库中的函数 SO() 解析了从 TIdHTTP 收到的响应正文,该函数与 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.

在上面的 sn-p 中,我使用TJSONObject.ParseJSONValue 来解析响应消息并将其附加到生成的 JSON 对象中。虽然我的响应消息存储在字符串常量中,但您可以轻松地调整解决方案以与TMemoryStreamTIdHTTP 一起使用。查看TJSONObject.ParseJSONValue 的所有不变量。

sn-p 产生输出:

{
    "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","SourceId":"215","SourceName":"MyVal1"},{"Active":"1","SourceId":"383","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.

【讨论】:

  • 感谢您为我指明了正确的方向。我的项目在 Delphi 2010 中,所以我无法使用该示例。然而,标准化到 iSuperObject 有很大帮助,修复就像 loResult.O['responseMessage'] := SO(lsRespMsg);
  • @Johan 我添加了 sn-p 以使用 SuperObject 执行相同的任务。下次记得把所有的限制放在你的问题中。我们看不到TJSONPairTJSONArray 来自哪里。
猜你喜欢
  • 2018-07-20
  • 1970-01-01
  • 1970-01-01
  • 2015-09-03
  • 1970-01-01
  • 1970-01-01
  • 2016-04-20
  • 1970-01-01
相关资源
最近更新 更多