【问题标题】:IdHttp : how to deal with json request and responseIdHttp:如何处理 json 请求和响应
【发布时间】:2016-12-27 15:56:35
【问题描述】:

我遇到过一些使用JSON 进行请求和响应的网站
我遇到两种类型:
1- application/x-www-form-urlencoded 作为请求并返回响应 application/json 内容类型
2- application/json 内容类型请求和响应
type 1 我尝试使用
mIdHttp.Response.ContentType := 'application/json';
更改响应内容类型 但是使用 http 分析器我可以看到它没有改变,它仍然是 text/html
现在我不知道问题是否在于我无法更改内容类型但我不知道如何处理json
关于json 的几个问题:
1- 发帖时我必须对 json 数据进行编码吗?如何?
2-如何解析 json 响应代码?如何得到它?是否需要某种编码或特殊转换?
3- json 的哪种 idhttp 设置会随每个站点而变化并需要配置?

我知道我的问题听起来有点笼统,但所有其他问题都非常具体,并且在处理 'application/json' 内容类型时没有解释基础知识。

编辑 1:
感谢 Remy Lebeau 的回答,我能够成功地使用 type 1
但我仍然无法发送JSON 请求,有人可以分享一个工作示例吗,这是发布信息的网站之一,请使用此示例:

一个重要提示:这个特定网站的帖子和请求内容完全一样!这让我感到困惑,因为在该站点上,我指定了一个 start date 和一个 end date 然后单击 folder like icon 并发送此 post(您可以在上面看到),并且 result 应该是links(确实如此)但是不仅出现在 request content 中,它们还出现在 post 中! (我也在尝试获取链接,但在post 链接,我想要的东西也正在发送,我怎么能发布我没有的东西!!?)

只是为了更清楚这里是我填写日期和我提到的图标的地方:

【问题讨论】:

  • 没有通用的解决方案。每个实现都可以不同。您可以控制是否希望 Indy 使用 FHTTP.HTTPOptions 中的 hoForceEncodeParams 对参数进行编码(如果您在请求中发送 JSON 数据,许多站点不允许编码请求)。你不应该设置Response.ContentType。这就是服务器返回的内容。您必须设置Request.ContentType(您发送的内容)和Request.Accept(您对服务器的期望)
  • @smooty86 hoForceEncodeParams 标志仅在以application/x-www-form-urlencoded 格式发布TStrings 时适用。它不适用于这种情况,因为您不能使用 TStrings 发布 JSON,而必须使用 TStream
  • @RemyLebeau 你打赌我可以在 TStrings 中发送 JSON :) 虽然我知道它可能不太有效。
  • 您像发送任何其他 Post 请求一样发送 JSON。提供您的代码发送方式。帖子中的“原始流”到底如何?解析模式下不清楚。
  • @smooty86 如果您使用TIdHTTP 发布TStrings,则它应该是“名称=值”对的列表,并且将被相应地编码。我还没有遇到一个接受类似“fieldname=json”作为输入的网站。不是说不能,而是极其罕见。 XML 也是如此。

标签: json delphi delphi-xe idhttp


【解决方案1】:

您不能指定响应的格式,除非请求的资源提供了明确的输入参数或专用 URL 用于该确切目的(即请求以 html、xml、json 等形式发送响应)。设置TIdHTTP.Response.ContentType 属性是没有用的。它将被响应的实际 Content-Type 标头覆盖。

要在请求中发送 JSON,您必须将其发布为TStream,如TMemoryStreamTStringStream,并根据需要设置TIdHTTP.Request.ContentType,例如:

var
  ReqJson: TStringStream;
begin
  ReqJson := TStringStream.Create('json content here', TEncoding.UTF8);
  try
    IdHTTP1.Request.ContentType := 'application/json';
    IdHTTP1.Post(URL, ReqJson);
  finally
    ReqJson.Free;
  end;
end;

接收 JSON,TIdHTTP 也可以

  1. 将其返回为 String(使用服务器报告的字符集解码):

    var
      ReqJson: TStringStream;
      RespJson: String;
    begin
      ReqJson := TStringStream.Create('json content here', TEncoding.UTF8);
      try
        IdHTTP1.Request.ContentType := 'application/json';
        RespJson := IdHTTP1.Post(URL, ReqJson);
      finally
        ReqJson.Free;
      end;
      // use RespJson as needed...
    end;
    
  2. 将原始字节写入您选择的输出TStream

    var
      ReqJson: TStringStream;
      RespJson: TMemoryStream;
    begin
      RespJson := TMemoryStream.Create;
      try
        ReqJson := TStringStream.Create('json content here', TEncoding.UTF8);
        try
          IdHTTP1.Request.ContentType := 'application/json';
          RespJson := IdHTTP1.Post(URL, ReqJson, RespJson);
        finally
          ReqJson.Free;
        end;
        RespJson.Position := 0;
        // use RespJson as needed...
      finally
        RespJson.Free;
      end;
    end;
    

TIdHTTP.Response.ResponseCode(和TIdHTTP.ResponseCode)属性中提供了 HTTP 响应代码。

【讨论】:

  • 你所说的对first type 有帮助,但我对second type 仍然有问题,我编辑了我的问题,请你阅读并相应地回答我,非常感谢!跨度>
  • @AliAhmadi 你到底有什么问题?您的编辑并没有使它更清晰。将 JSON 内容按原样放入 TStream 后代然后发布它有什么难的?你一开始就知道如何生成 JSON 吗?
  • produce JSON 是什么意思,也许这是我的问题? (就像我说的,我不知道JSON 的基础知识,一个简单的例子就足够了,谢谢)
  • @AliAhmadi:我在答案中添加了示例。但是,如果您一开始不知道如何生成 JSON,您希望如何发送它呢?见Embarcadero's JSON documentation
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-22
  • 2011-02-23
  • 2021-12-02
  • 1970-01-01
  • 1970-01-01
  • 2020-04-12
  • 1970-01-01
相关资源
最近更新 更多