【问题标题】:HttpClient.GetStringAsync is returning a "Result" object?HttpClient.GetStringAsync 正在返回“结果”对象?
【发布时间】:2019-08-17 19:35:38
【问题描述】:

我正在尝试使用 GetStringAsync 方法从我自己的 API 中检索 JSON 列表。 当我得到它时,它作为“结果”对象返回,而不仅仅是一个字符串?

然后我尝试将 JSON 数组反序列化为列表,但收到错误。

从 HttpCLient.GetStringAsync 看,DEBUGGER 中返回的字符串是这样的:

"{\"Result\":[{\"id\":92,\"name\":\"Chris Hemsworth\",\"birthDate\":\"1983-8-11\",\"role\":\"Producer\",\"originalList\":null},{\"id\":90,\"name\":\"Jennifer Aniston\",\"birthDate\":\"1969-2-11\",\"role\":\"Producer\",\"originalList\":null},{\"id\":40,\"name\":\"Edward Norton\",\"birthDate\":\"1969-8-18\",\"role\":\"Writer\",\"originalList\":null}],\"Id\":71,\"Exception\":null,\"Status\":5,\"IsCanceled\":false,\"IsCompleted\":true,\"CreationOptions\":0,\"AsyncState\":null,\"IsFaulted\":false}"

尝试将 JSON 对象转换为字符串时遇到的异常:

Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[BuisnessLogic.Actor]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.Path 'Result', line 1, position 10.'

更新:

代码如下:

var celebrities = JsonConvert.DeserializeObject<List<Actor>>(await client.GetStringAsync($"{serverAddress}/values/{GET_CELEBS_COMMAND}"));

Actor 类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BuisnessLogic
{
    public class Actor
    {
        public int id { get; set; }
        public string name { get; set; }
        public string birthDate { get; set; }
        public string role { get; set; }
        public List<Actor> originalList { get; set; }

        public Actor(string name, string birthDate, string role)
        {
            this.name = name;
            this.birthDate = birthDate;
            this.role = role;
        }

        public Actor()
        {

        }

        public override string ToString()
        {
            return "Person: " + id + "" + name + " " + birthDate + " " + role;
        }

    }
}

编辑 2:

控制器:

  using BuisnessLogic;

using System.Web.Mvc;

namespace WebApplication12.Controllers
{
    public class ValuesController : Controller
    {
        public ILogic _Ilogic;
        public ValuesController(ILogic logic)
        {
            _Ilogic = logic;

        }

        // GET api/values

        public ActionResult GetActors()
        {
            return Json(_Ilogic.GetAllActorsAsync(), JsonRequestBehavior.AllowGet);
        }

    }
}

数据管理类:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Configuration;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using System.Linq;


namespace BuisnessLogic
{
    public class Logic : ILogic
    {
        static string filePath;
        private static ConcurrentDictionary<string, Actor> originalList;
        const string BACKUP = @"D:\backup.txt";

        static Logic()
        {
            originalList = new ConcurrentDictionary<string, Actor>();
            filePath = ConfigurationManager.AppSettings["tempList"];
            File.Copy(filePath, BACKUP, true);
            SaveOriginal();
        }



        public async static Task<List<Actor>> GetCelebritiesInner()
        {
            return originalList.Values.ToList();
        }

        public async Task<List<Actor>> GetAllActorsAsync()
        {
            return await GetCelebritiesInner();
        }




        // Try to read the data from the Json and initialize it. if failed , initialize with whatever it got. return 
        private static List<Actor> ReadActorsFromJson(string json)
        {
            List<Actor> celebListReadFromFile;
            try
            {

                var celebJson = File.ReadAllText(json);
                celebListReadFromFile = JsonConvert.DeserializeObject<List<Actor>>(celebJson);

            }
            catch (Exception ex)
            {
                celebListReadFromFile = new List<Actor>();
                // Empty list/whatever it got in it
            }
            return celebListReadFromFile;
        }

        public async Task RemoveActorAsync(string name)
        {

            if (originalList.TryRemove(name, out Actor removedActor))
            {
                var jsonToWrite = JsonConvert.SerializeObject(await GetCelebritiesInner());

                try
                {

                    File.WriteAllText(filePath, jsonToWrite);
                }
                catch (Exception ex)
                {
                    //Unable to remove due to an error.

                }
            }
        }

        public async Task ResetAsync()
        {

            UpdateFile();
        }

        //Saving the actor, adding the name as key & object as value.
        public static void SaveOriginal()
        {
            foreach (var currCeleb in ReadActorsFromJson(filePath))
            {
                originalList.TryAdd(currCeleb.name, currCeleb);
            }
        }

        public static void UpdateFile()
        {
            File.WriteAllText(filePath, string.Empty);
            var text = File.ReadAllText(BACKUP);
            File.WriteAllText(filePath, text);
        }
    }
}

进入uri并获取字符串的更新方法:

public async void update()
    {
        var b = await client.GetStringAsync($"{serverAddress}/values/{GET_CELEBS_COMMAND}");

        var celebrities = JsonConvert.DeserializeObject<List<Actor>>(b);
        foreach (Actor actor in celebrities)
        {
            actorBindingSource.Add(actor);
        }
    }

【问题讨论】:

  • “看起来像”,您在哪里确切地看到了这样的字符串?我问因为反斜杠,您是否使用调试器看到该字符串,或者您是否将其写入文件或控制台或诸如此类?请具体
  • 看起来您的 API 正在序列化 Task&lt;T&gt; 而不仅仅是 T。在 API 的某处缺少await
  • Lasse Vågsæther Karlsen ,我从调试器中得到了那个字符串

标签: c# asp.net winforms httpclient dotnet-httpclient


【解决方案1】:

您问题中显示的 JSON 是Task&lt;T&gt; 的序列化实例,其中包括ResultAsyncStateIsFaulted 等属性。很明显,这应该是T 的序列化实例(在您的情况下为List&lt;Actor&gt;),这通常意味着某处缺少await

这个“丢失的await”在您的ValuesController.GetActors 中,它将ILogic.GetAllActorsAsync 的结果传递给Json。这最终会传入一个Task&lt;List&lt;Actor&gt;&gt; 的实例,而不仅仅是List&lt;Actor&gt;。为了解决这个问题,请使用await,如下所示:

public async Task<ActionResult> GetActors()
{
    return Json(await _Ilogic.GetAllActorsAsync(), JsonRequestBehavior.AllowGet);
}

这也需要GetActors async,正如我在上面展示的那样。

【讨论】:

    【解决方案2】:

    首先将**Result** 替换为Result

    var stringResult = await HttpCLient.GetStringAsync().Replace("**Result**", "Result");
    

    第二次创建与json结果具有相同属性的类。

    public class JsonResult
    {
        public List<ResultObject> Result { get; set; }
    
        public int Id { get; set; }
        public string Exception { get; set; }
        public int Status { get; set; }
        public bool IsCanceled { get; set; }
        public bool IsComplete { get; set; }
        public int CreationOptions { get; set; }
        public string AsyncState { get; set; }
        public bool IsFaulted { get; set; }
    }
    
    public class ResultObject
    {
        public int id { get; set; }
        public string name { get; set; }
        public string birthDate { get; set; }
        public string role { get; set; }
        public string originalList { get; set; }
    }
    

    然后反序列化字符串:

    var resultObject = JsonConvert.DeserializeObject<JsonResult>(result);
    

    resultObject 将包含整个结果。

    【讨论】:

    • 对不起,“***结果**”是我想在这里加粗,它不在代码中,我确实有一个与 json 结果具有相同属性的对象,抱歉没有包含它,我将编辑原始帖子
    • 哦,伙计……看看我的代码。只需将 Result 类包装在您的 Actor 类周围,它就会起作用。只需阅读我的回答,请阅读 Newtonsoft 的文档。
    • 感谢您的回复,即使在使用 JsonResult 对象包装我的 Actor 类后,我也遇到了同样的错误。 var 名人 = JsonConvert.DeserializeObject>(b);
    • 奇怪的是我什至不希望 JsonResult 成为 Json 的一部分,而且我不知道它来自哪里,哈哈,Json 中应该只有 ResultObject,很奇怪。跨度>
    • 在您的第二次编辑后,我终于遇到了您的问题。柯克·拉金 (Kirk Larkin) 有正确的解决方案。
    猜你喜欢
    • 2023-01-26
    • 2021-06-09
    • 1970-01-01
    • 2011-07-10
    • 2020-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-09
    相关资源
    最近更新 更多