有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java使用Indy和Delphi发送JSON编码的对象

我在这个问题上花了太多的时间,但没有取得任何进展。我有一个旧的解决方案,可以工作,但我正在尝试将其移植到Indy,以使代码更可靠,更易于维护

我们有一个servlet,它使用HTTP POST消息处理发送给它的请求。这些消息只有一个参数“command”,其值决定servlet应该做什么

目前我有:

procedure TIndyLoginServer.SendRequest(Command, Json: string; Request: TRequest);
var
  Params: TIdStrings;
  ServerResponse: string;
begin
  // Build parameters
  Params := TStringList.Create();
  Params.Add('command=' + Command);

  try
    // Content type should really be 'application/json' but then the parameters stop working
    FIndyHttp.Request.ContentType := 'application/x-www-form-urlencoded'; 
    ServerResponse := FIndyHttp.Post(FUrl, Params);
    Request.OnRequestFinished(ServerResponse, '', '');
  except
    on E: EIdHTTPProtocolException do
    begin
      Request.OnRequestFinished('', E.Message, '');
    end;
    on E: EIdSocketError do
    begin
      if E.LastError = Id_WSAETIMEDOUT then      
        Request.OnRequestTimedOut();
    end;
    on E: EIdException do
    begin
      Request.OnRequestFinished('', E.Message, '');
    end;
  end;
end;

这种情况下,命令到达servlet并开始按预期工作。问题是,除了参数之外,我还需要能够在POST请求中发送JSON编码的对象。Javaservlet使用以下代码行接收JSON编码的对象

final BufferedReader r = req.getReader();

“req”显然是传入的POST请求,缓冲读取器稍后用于解码对象。然而,在我的一生中,我无法弄清楚如何以servlet可以读取数据的方式将JSON字符串附加到TIDWTTP实例

有谁能给我一些建议或例子吗?我所发现的只是如何发送文件。也许这就是我要找的

如何在不破坏参数列表的情况下将请求的内容类型设置为“application/json”?如果我更改它,POST请求仍然会到达服务器,但是“command”参数不再存在


共 (2) 个答案

  1. # 1 楼答案

    我想我解决了。我不确定这是做这件事的最美丽的方式,但它似乎做了我想要的

    这是密码

    procedure TIndyLoginServer.SendRequest(Command, Json: string;
      Request: TRequest);
    var
      JsonToSend: TIdStringStream;
      ServerResponse: string;
      Url: string;
    begin
      // Build parameters
      JsonToSend := TIdStringStream.Create(Json);
    
      try
        try
          FIndyHttp.Request.Accept := 'application/json';
          FIndyHttp.Request.ContentType := 'application/json';
          FIndyHttp.Request.ContentEncoding := 'utf-8';
    
    
          Url := FUrl +'?command=' + Command;
          ServerResponse := FIndyHttp.Post(Url, JsonToSend);
    
          Request.OnRequestFinished(ServerResponse, '', '');
        except
          on E: EIdHTTPProtocolException do
          begin
            Request.OnRequestFinished('', E.Message, '');
          end;
          on E: EIdSocketError do
          begin
            if E.LastError = Id_WSAETIMEDOUT then
              Request.OnRequestTimedOut();
          end;
          on E: EIdException do
          begin
            Request.OnRequestFinished('', E.Message, '');
          end;
        end;
      finally
        JsonToSend.Free();
      end;
    end;
    
  2. # 2 楼答案

    主要是一个提示:当您使用“application/x-www-form-urlencoded”时,服务器端希望看到如下键/值对:

    key1=value1&key2=value2 etc.
    

    在这种情况下,您可以将JSON文本作为键的值发送,例如:

    {...}
    Params.Add('command=' + Command);
    Params.Add('jsonText=' + json);
    FIndyHttp.Request.ContentType := 'application/x-www-form-urlencoded'; 
    ServerResponse := FIndyHttp.Post(FUrl, Params);
    {...}
    

    使用“application/json”可以对HTTP服务器说:请求的整个主体(标题后的部分)将包含json文本

    在PHP中,我可以使用“输入流”访问请求的“正文”:

    $jsonText = file_get_contents("php://input")
    $jsonObject = json_decode($jsonText )
    

    试着在JAVA中找到类似的东西

    更新:

    似乎TIdStrings将请求准备为“application/x-www-form-urlencoded”。 AsRemy Lebeau suggests here将JSON字符串保存到TStream子体(例如tMemoryStream)并按原样传输(即原始)。tIdHttp。POST具有接受TStream的覆盖。 在这种情况下,请尝试使用TIdHTTP。要求ContentType='application/json'。应该是这样的吗