C# HttpClient 无法将 POST 响应读取为 JSON

c# httpclient unable to read post response as json

提问人:user1538142 提问时间:2/1/2022 最后编辑:user1538142 更新时间:2/1/2022 访问量:3905

问:

我无法让我的 dotnet web api (v. 5.0) 从另一个 API 读取 json 响应。 它坚持用 \ “装饰”字符串并删除引号。我怀疑它假设返回的内容是某种格式,然后尝试将 json 内容“反序列化”为字符串。

我的 API 返回此

{
    "result": [
        {
            "CampaignId": 1
        }
    ]
}

根据邮递员的说法,返回的原始数据是 {“结果”:[{“CampaignId”:1}]}

这似乎是合理的。

问题是,在以下代码中responseContent

var bodyStr = body.ToString();
var client = new HttpClient();
var httpContent = new StringContent(bodyStr, Encoding.UTF8, "application/json");
var response = await client.PostAsync("http://anotherapi/query",httpContent);            
var responseContent = await response.Content.ReadAsStringAsync();

返回

"{\"result\":[{CampaignId:1}]}"

当它作为 JSON 读取时,这显然会失败

using (JsonDocument document = JsonDocument.Parse(responseContent)) {}

编辑: 调用时,我收到以下异常:JsonDocument.Parse(responseContent)

System.Text.Json.JsonReaderException: 'C' is an invalid start of a property name. Expected a '"'. LineNumber: 0 | BytePositionInLine: 12.

因为似乎删除了“CampaignId”周围的引号,这使得 json 无效。ReadAsStringAsync()

EDIT2:根据 postman 的说法,这是来自其他 API 的返回响应:Postman response RAW

这是响应标头:Response header

这是根据 curl 的响应:

$ curl --data "@/somedata.txt" -X POST -H "Content-Type: application/json" http://host/query
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 19847  100    30  100 19817     30  19817  0:00:01  0:00:01 --:--:-- 16083{"result":[{"CampaignId":1}]}

我没有看到响应标头或内容有任何问题。返回的内容似乎一切正常,“campaignId”包含引号。

C# JSON HttpClient 引用 HttpResponseMessage

评论

0赞 Dai 2/1/2022
它是如何失败的?你有例外吗?还是只是 ?null
1赞 Dai 2/1/2022
你只在调试器中看到吗?如果是这样,那么这很正常:反斜杠实际上不在字符串中。但是,如果没有更多错误信息,我们将无法为您提供帮助。"{\"result\":[{CampaignId:1}]}"
1赞 Dai 2/1/2022
是的,您应该使用 Fiddler,因为我们需要查看 的原始网络流量。HttpClient
1赞 user1538142 2/1/2022
@Dai你是对的。通过 wireshark 分析了包,CampaignId 确实没有在响应包中包含引号。
1赞 Dai 2/1/2022
做对了感觉真好:)

答:

1赞 user1538142 2/1/2022 #1

返回响应的 mormot API 没有在 campaignId 周围添加引号,因为它使用了自己的扩展 JSON 格式。

它使用扩展的 JSON 格式,因为用户代理未在请求标头中设置。

向我的 httpclient 添加一个默认标头,使其工作:

var client = new HttpClient();
var productValue = new ProductInfoHeaderValue("A Header", "1.0");
var commentValue = new ProductInfoHeaderValue("(a comment)");

client.DefaultRequestHeaders.UserAgent.Add(productValue);
client.DefaultRequestHeaders.UserAgent.Add(commentValue);

评论

0赞 Dai 2/1/2022
考虑缓存 a 以减少 GC 分配。static readonly ProductInfoHeaderValue
0赞 Serge 2/1/2022 #2

您可以尝试将此标头添加到您的 HttpClient 中,也许它会有所帮助

client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

但我强烈建议你使用 Newtonsoft.Json。任何其他序列化器都只适用于序列化“Hello World!使用 Newtonsoft.Json,我可以毫无问题地解析您的 json

using Newtonsoft.Json;


var json="{\"result\":[{CampaignId:1}]}";
    
var jsonObject= JObject.Parse(json);

如果要修复 JSON,只需再次将解析的对象转换为 JSON 即可

json=jsonObject.ToString();

结果

{
  "result": [
    {
      "CampaignId": 1
    }
  ]
}

现在,您可以使用任何您喜欢的序列化程序。如果您使用的是 net API,最好向我们展示您的 APi 代码和启动代码。我们可以帮助您将另一个序列化程序分配给 Api 控制器,它将以正确的格式返回 json。