delphi7 idhttp post json


datastr:='{"name":"蜂窝纸70克30宽50米-中强",
"product_no":"CN.01.0700308888001",
"cn_name":"蜂窝纸70克30宽50米-中强",
"category_ids":[23,190003341,190003350],
"group_id":"纸垫类成品",
"6076727299027":"HP-Z-30-70-50",
"cost_currency":"USD",
"cost":"0",
"cost_unit":""}';
IdHTTP1.Request.Accept:='application/json';
IdHTTP1.HandleRedirects :=True;
IdHTTP1.Request.ContentType:='application/x-www-form-urlencoded';
IdHTTP1.Request.CustomHeaders.Text:='Authorization:'+crmtoken ;
sGetTokenURL:='https://xxxxx.cn' ;
jsonToSend := TStringStream.Create(datastr);
jsonToSend.Position := 0;
sResult:=Utf8ToAnsi(IdHTTP1.Post(sGetTokenURL,jsonToSend)) ; 

运行提示 HTTP/1.1 400 bad Request ,跟踪发现
"category_ids":[23,190003341,190003350] 数组变成了字符 "category_ids":“[23,190003341,190003350]“ ,请问要如何调整?

参考GPT和自己的思路:在进行 HTTP POST 请求时,根据指定的 Content-Type,需要对请求体数据进行相应的编码处理。如果使用了 application/x-www-form-urlencoded 编码方式,那么需要将数据编码成类似 key1=value1&key2=value2 的格式;如果使用 application/json 编码方式,则需要将数据编码成 JSON 字符串。

在你的代码中,请求头中设置的 Content-Type 为 application/x-www-form-urlencoded,但请求体数据却是一个 JSON 字符串。这种情况下,请求体数据需要先被编码成类似 key1=value1&key2=value2 的格式,然后再通过 IdHTTP1.Post 方法发送。

另外,在数据编码成 application/x-www-form-urlencoded 格式时,数组需要使用多个相同的键名进行编码。因此,你需要将 JSON 数据中的 category_ids 字段转换成类似 category_ids[]=23&category_ids[]=190003341&category_ids[]=190003350 的格式。可以使用 Delphi 内置的 TJSON 单元解析 JSON 数据,然后使用循环遍历数组元素,将其拼接成正确的格式。

以下是示例代码:

var
  datastr: string;
  jsonToSend: TStringStream;
  sResult: string;
  sGetTokenURL: string;
begin
  datastr := '{"name":"蜂窝纸70克30宽50米-中强",
  "product_no":"CN.01.0700308888001",
  "cn_name":"蜂窝纸70克30宽50米-中强",
  "category_ids":[23,190003341,190003350],
  "group_id":"纸垫类成品",
  "6076727299027":"HP-Z-30-70-50",
  "cost_currency":"USD",
  "cost":"0",
  "cost_unit":""}';

  IdHTTP1.Request.Accept := 'application/json';
  IdHTTP1.HandleRedirects := True;
  IdHTTP1.Request.ContentType := 'application/json';
  IdHTTP1.Request.CustomHeaders.Text := 'Authorization:' + crmtoken;
  sGetTokenURL := 'https://xxxxx.cn';

  jsonToSend := TStringStream.Create(datastr, TEncoding.UTF8);
  try
    sResult := IdHTTP1.Post(sGetTokenURL, jsonToSend);
  finally
    jsonToSend.Free;
  end;

  // 处理响应
end;


在上述代码中,我们使用了 TStringStream 将 datastr 包装成一个 JSON 格式的数据流,然后将其作为 POST 请求的正文发送给服务器。同时,我们指定了请求的 Content-Type 为 application/json,这样服务器就可以正确解析我们发送的 JSON 数据。如果服务器返回的响应也是 JSON 格式的数据,您可以使用 Delphi 内置的 TJSONObject 或第三方库(如 SuperObject)来解析响应。

该回答引用GPTᴼᴾᴱᴺᴬᴵ
您可以使用 TJSONObject 和 TJSONArray 来构建您的 JSON 数据,这样可以确保数组数据不会被转化为字符串。

以下是一个示例代码:

uses
  System.JSON;

var
  jsonObj: TJSONObject;
  jsonArray: TJSONArray;
  datastr: string;
begin
  jsonArray := TJSONArray.Create;
  jsonArray.Add(23);
  jsonArray.Add(190003341);
  jsonArray.Add(190003350);

  jsonObj := TJSONObject.Create;
  jsonObj.AddPair('name', '蜂窝纸70克30宽50米-中强');
  jsonObj.AddPair('product_no', 'CN.01.0700308888001');
  jsonObj.AddPair('cn_name', '蜂窝纸70克30宽50米-中强');
  jsonObj.AddPair('category_ids', jsonArray);
  jsonObj.AddPair('group_id', '纸垫类成品');
  jsonObj.AddPair('6076727299027', 'HP-Z-30-70-50');
  jsonObj.AddPair('cost_currency', 'USD');
  jsonObj.AddPair('cost', '0');
  jsonObj.AddPair('cost_unit', '');

  datastr := jsonObj.ToJSON;

  IdHTTP1.Request.Accept := 'application/json';
  IdHTTP1.HandleRedirects := True;
  IdHTTP1.Request.ContentType := 'application/json';
  IdHTTP1.Request.CustomHeaders.Text := 'Authorization:' + crmtoken;
  sGetTokenURL := 'https://xxxxx.cn';
  sResult := Utf8ToAnsi(IdHTTP1.Post(sGetTokenURL, datastr));
end;

这个示例使用 TJSONObject 和 TJSONArray 来构建 JSON 对象,确保了 category_ids 是一个数组而不是字符串。TJSONObject 和 TJSONArray 是 Delphi 自带的类,可以很方便地用来构建和解析 JSON 数据。

参考GPT和自己的思路:

在这段代码中,使用了 TStringStream 来将 JSON 数据传递给 idHTTP,但是由于 ContentType 被设置为 'application/x-www-form-urlencoded',所以 idHTTP 将会把数据当作表单的键值对进行处理,因此会把数组转换成字符串,导致请求失败。

为了解决这个问题,可以将 ContentType 设置为 'application/json',并修改代码如下:

1. datastr:='{"name":"蜂窝纸70克30宽50米-中强",
2. "product_no":"CN.01.0700308888001",
3. "cn_name":"蜂窝纸70克30宽50米-中强",
4. "category_ids":[23,190003341,190003350],
5. "group_id":"纸垫类成品",
6. "6076727299027":"HP-Z-30-70-50",
7. "cost_currency":"USD",
8. "cost":"0",
9. "cost_unit":""}';
10. IdHTTP1.Request.Accept:='application/json';
11. IdHTTP1.HandleRedirects :=True;
12. IdHTTP1.Request.ContentType:='application/json';
13. IdHTTP1.Request.CustomHeaders.Text:='Authorization:'+crmtoken ;
14. sGetTokenURL:='https://xxxxx.cn' ;
15. jsonToSend := TStringStream.Create(datastr, TEncoding.UTF8);
16. try
17.   sResult := IdHTTP1.Post(sGetTokenURL, jsonToSend);
18. finally
19.   jsonToSend.Free;
20. end;

在修改了 ContentType 后,将数据转换成 UTF8 编码的字符串流,并在 Post 方法的第二个参数传入即可。这样服务器就能正确地解析出 category_ids 数组。

该回答引用ChatGPT

如有疑问,可以回复我!

根据您的问题描述,问题似乎出在“category_ids”数组在发送请求时被转换为字符串。为了解决这个问题,您可以尝试使用 TJSONObject 和 TJSONArray 进行 JSON 数据的构建,然后使用 TJson.Format 函数将其转换为字符串。以下是一个示例代码:


uses
  System.JSON;

var
  dataJson: TJSONObject;
  categoryIdsArray: TJSONArray;
begin
  dataJson := TJSONObject.Create;
  try
    dataJson.AddPair('name', '蜂窝纸70克30宽50米-中强');
    dataJson.AddPair('product_no', 'CN.01.0700308888001');
    dataJson.AddPair('cn_name', '蜂窝纸70克30宽50米-中强');
    
    categoryIdsArray := TJSONArray.Create;
    categoryIdsArray.Add(23);
    categoryIdsArray.Add(190003341);
    categoryIdsArray.Add(190003350);
    dataJson.AddPair('category_ids', categoryIdsArray);

    dataJson.AddPair('group_id', '纸垫类成品');
    dataJson.AddPair('6076727299027', 'HP-Z-30-70-50');
    dataJson.AddPair('cost_currency', 'USD');
    dataJson.AddPair('cost', '0');
    dataJson.AddPair('cost_unit', '');

    IdHTTP1.Request.Accept := 'application/json';
    IdHTTP1.HandleRedirects := True;
    IdHTTP1.Request.ContentType := 'application/x-www-form-urlencoded';
    IdHTTP1.Request.CustomHeaders.Text := 'Authorization:' + crmtoken;
    sGetTokenURL := 'https://xxxxx.cn';

    jsonToSend := TStringStream.Create(TJson.Format(dataJson));
    jsonToSend.Position := 0;
    sResult := Utf8ToAnsi(IdHTTP1.Post(sGetTokenURL, jsonToSend));

  finally
    dataJson.Free;
  end;
end;

这段代码将构建一个 TJSONObject,并使用 TJSONArray 来存储 category_ids 数组。然后,使用 TJson.Format 将 TJSONObject 转换为字符串。这样在发送请求时,category_ids 仍然保持为数组格式。

参考GPT和自己的思路,问题在于JSON中的 "category_ids" 键值对值不是一个数组,而是一个字符串。

为了解决这个问题,您可以在创建 JSON 字符串时,将 "category_ids" 键值对的值改为实际的 JSON 数组。可以使用以下方式来创建 JSON 数组:

"category_ids": [23, 190003341, 190003350]

使用上述方式将 "category_ids" 键值对值设置为 JSON 数组,可以解决这个问题。以下是更新后的代码示例:

datastr := '{"name":"蜂窝纸70克30宽50米-中强",
"product_no":"CN.01.0700308888001",
"cn_name":"蜂窝纸70克30宽50米-中强",
"category_ids":[23,190003341,190003350],
"group_id":"纸垫类成品",
"6076727299027":"HP-Z-30-70-50",
"cost_currency":"USD",
"cost":"0",
"cost_unit":""}';

IdHTTP1.Request.Accept := 'application/json';
IdHTTP1.HandleRedirects := True;
IdHTTP1.Request.ContentType := 'application/x-www-form-urlencoded';
IdHTTP1.Request.CustomHeaders.Text := 'Authorization:' + crmtoken;
sGetTokenURL := 'https://xxxxx.cn';
jsonToSend := TStringStream.Create(datastr);
jsonToSend.Position := 0;
sResult := Utf8ToAnsi(IdHTTP1.Post(sGetTokenURL, jsonToSend));

希望这可以帮助您解决问题!

需要将该字符串转换为数组格式。可以使用 JSON.parse() 方法将该字符串解析为数组,示例:
let categoryIdsStr = "[23,190003341,190003350]";
let categoryIdsArr = JSON.parse(categoryIdsStr);
console.log(categoryIdsArr);
// 输出: [23, 190003341, 190003350]
然后再将该数组赋值给对应的属性即可。

参考GPT和自己的思路。根据您提供的代码和信息,我猜测可能是双引号的问题导致了数据发送的格式错误,可以尝试在datastr中将 category_ids 数组的元素以及核心值都用双引号引起来,例如这样: Delphi datastr:='{"name":"蜂窝纸70克30宽50米-中强", "product_no":"CN.01.0700308888001", "cn_name":"蜂窝纸70克30宽50米-中强", "category_ids":["23","190003341","190003350"], "group_id":"纸垫类成品", "6076727299027":"HP-Z-30-70-50", "cost_currency":"USD", "cost":"0", "cost_unit":""}'; 这里修改了 category_ids 数组中的值,用双引号包裹起每个元素,再尝试重新运行程序看是否可以解决问题。希望我可以帮助到你,祝你天天开心😁

先定义一个let categoryIdsStr = "[23,190003341,190003350]";然后在塞到

datastr:='{"name":"蜂窝纸70克30宽50米-中强",
"product_no":"CN.01.0700308888001",
"cn_name":"蜂窝纸70克30宽50米-中强",
"category_ids":categoryIdsStr ,
"group_id":"纸垫类成品",
"6076727299027":"HP-Z-30-70-50",
"cost_currency":"USD",
"cost":"0",
"cost_unit":""}

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
您好,根据您提供的代码和数据,可以尝试以下方法:

  1. 将传递的JSON数据格式为Content-Type为application/json时使用的格式。
  2. 使用Delphi内置的JSON库JsonDataObjects对JSON数据进行序列化,将序列化后的JSON字符串传递给IdHTTP。

代码示例如下:

uses
  JsonDataObjects;

var
  Json: TJDOJsonObject;
  JsonStr: string;
begin
  Json := TJDOJsonObject.Create;
  try
    // 构建JSON对象
    Json.S['name'] := '蜂窝纸70克30宽50米-中强';
    Json.S['product_no'] := 'CN.01.0700308888001';
    Json.S['cn_name'] := '蜂窝纸70克30宽50米-中强';
    Json.A['category_ids'].Add(23);
    Json.A['category_ids'].Add(190003341);
    Json.A['category_ids'].Add(190003350);
    Json.S['group_id'] := '纸垫类成品';
    Json.S['6076727299027'] := 'HP-Z-30-70-50';
    Json.S['cost_currency'] := 'USD';
    Json.S['cost'] := '0';
    Json.S['cost_unit'] := '';

    // 将JSON对象序列化为JSON字符串
    JsonStr := Json.ToJSON;

    // 发送POST请求
    IdHTTP1.Request.CustomHeaders.Clear;
    IdHTTP1.Request.CustomHeaders.AddValue('Authorization', crmtoken);
    IdHTTP1.Request.ContentType := 'application/json';
    IdHTTP1.HandleRedirects := True;
    sResult := Utf8ToAnsi(IdHTTP1.Post(sGetTokenURL, TStream.Create(JsonStr)));
  finally
    Json.Free;
  end;
end;

值得一提的是,在本示例当中,借助了Delphi的一个类库JsonDataObjects,用于序列化和反序列化JSON数据,这个库非常轻巧但功能强大。

另外,使用Post方法发送JSON数据时,需要传递一个TStream类型的参数,而不是TStringStream。因此,本示例使用了TStream.Create(JsonStr)来创建一个TStream对象。

希望本示例能够解答您的问题并得到帮助。
如果我的回答解决了您的问题,请采纳!

在Apipost 测试 post  是成功,body :raw json   
{
  "name":"吹尘枪",
  "product_no":"FL.5.289919999001",
  "group_id":"纸垫类成品",
  "category_ids":[23,190003341,190003350],
  "6076727299027":"吹尘枪;出风管类型",
  "cost_currency":"USD",
  "cost":"0",
  "cost_unit":""
}

```
用delphi7 idhttp 一直提示 HTTP/1.1 400 bad Request,之前说是 category_ids 数组被当成字符处理了,但是我不传 category_ids ,也提示一样的错误。

不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^