【问题标题】:Deserialize JSON object xamarin C#反序列化 JSON 对象 xamarin C#
【发布时间】:2017-07-04 06:51:06
【问题描述】:

我在反序列化 JSON 对象时在 Xamarin 跨平台中收到以下错误。我试过用字典来做。但是,一切都给了我同样的例外。

Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON object (e.g. {\"name\":\"value\"}) into type 'System.Collections.Generic.List`1[NBStudents.Models.jsonobjectclass+User]' 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 'data.name', line 4, position 11.

我的 JSON 对象类:

public class jsonobjectclass
{
    public class User
    {
        public string name { get; set; }
        public string email { get; set; }
        public string phone { get; set; }
        public string current_group { get; set; }
        public List<UserGroups> user_groups { get; set; }
    }

    public class UserGroups
    {
        [JsonProperty("10")]
        public string Student { get; set; }
        [JsonProperty("15")]
        public string Tutor { get; set; }
        [JsonProperty("11")]
        public string Parent { get; set; }
    }

    public class Token
    {
        public string access_token { get; set; }
        public int expires_in { get; set; }
        public string token_type { get; set; }
        public string scope { get; set; }
        public string refresh_token { get; set; }
        public string error { get; set; }
    }


    public class UserResponse
    {
        public string msg { get; set; }
        public List<User> data { get; set; }
        public bool error { get; set; }
    }
}

我的反序列化 JSON 代码:

public static async Task<jsonobjectclass.UserResponse> UserRetrievalTask(string token, string apiUrl)
    {
        var jsonObject = new jsonobjectclass.UserResponse();
        string readHttpResponse;

        using (var httpClient = new HttpClient())
        {
            using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, apiUrl))
            {
                httpRequestMessage.Headers.Add("Authorization", "Bearer " + token); 
                using (var httpResponse = await httpClient.SendAsync(httpRequestMessage).ConfigureAwait(false))
                {
                    readHttpResponse = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
                    var jObject = JObject.Parse(readHttpResponse);
                    try
                    {
                        jsonObject = JsonConvert.DeserializeObject<jsonobjectclass.UserResponse>(jObject.ToString());
                    }
                    catch(Exception ex)
                    {
                        string excep = ex.ToString();
                        readHttpResponse = excep;
                    }
                }
            }
        }
        return jsonObject;
    }

我的 JSON 字符串:

{{
  "msg": null,
  "data": {
  "name": "geoit",
  "email": "rokesh@geoit.in",
  "phone": null,
  "current_group": "11",
  "user_groups": {
   "11": "Parent"
   }
},
"error": false
}}

请帮我解决这个问题。

谢谢, 罗克什

【问题讨论】:

  • 发布你的 json 字符串
  • 阅读How to Ask 并创建一个minimal reproducible example。所有 HTTP 代码都无关紧要,相关部分,即 JSON 字符串,不在您的问题中。
  • 在收到响应后显示 readHttpResponse 的值
  • 这不是一个有效的 JSON。使用在线验证器来验证 json.. jsonlint.com/https://jsonlint.com
  • 你真的有像 {{ }} 或 {} 这样的双括号

标签: c# .net json xamarin serialization


【解决方案1】:

字符串与您尝试反序列化的对象不匹配。 data 对象不是一个数组,并且还有一个额外的嵌套对象,它没有在 JSON 中单独命名,包含 msg 字段和 user 数据,但 error 字段不是该对象的一部分:

正如 cmets 指出的那样,JSON 是无效的,所以如果你可以控制源,我会解决这个问题。

如果没有,您可以实现一个阅读器并将其解析为一个令牌一个令牌,如下所示:

using (var response = await client.GetAsync(_url, HttpCompletionOption.ResponseHeadersRead))
using (var stream = await response.Content.ReadAsStreamAsync())
using (var streamReader = new StreamReader(stream))
using (var reader = new JsonTextReader(streamReader))
{

    var serializer = new JsonSerializer();      

    while (reader.Read())
    {
        switch (reader.TokenType)
        {
            case JsonToken.Start:
            // code to handle it
            break;
            case JsonToken.PropertyName:
            // code to handle it
            break;

            // more options 
        }
    }       
}

虽然这种方法比较脆弱。您可以查看The JSON.Net JsonToken docs 了解更多信息。

根据您的评论并使用https://jsonlint.com/ 响应字符串

"{\"msg\":null,\"data\":{\"name\":\"geoit\",\"email\":\"roke‌​sh@geoit.in\",\"phon‌​e\":null,\"current_g‌​roup\":\"11\",\"user‌​_groups\":{\"11\":\"‌​Parent\"}},\"error\"‌​:false}"

实际上是有效的 JSON,但对象有点奇怪。我认为它在 C# 中看起来像这样

public class UserGroup
{
    public string 11 { get; set; }
}

public class UserData {
    public string name  { get; set; }
    public string email  { get; set; }
    public string phone  { get; set; }
    public string current_group  { get; set; }
    public UserGroup user_groups  { get; set; }
}

public class ResponseObject
{    
    public string msg { get; set; }
    public UserData data  { get; set; }
    public bool error  { get; set; }
}

【讨论】:

  • 哇...!!真的对我有用,谢谢哥们... :-)
  • 令牌方法还是 C# 对象?事件虽然是有效的 JSON / C# POCO,但我不禁认为源没有正确序列化。拥有“11”的属性很奇怪
  • 是的,主要是我应该使用类对象public UserData data { get; set; } 而不是列表数组public List&lt;UserData&gt; data { get; set; } ...太好了!!谢谢!!
【解决方案2】:

它应该是一个数组,左括号和右括号应该是方括号:

[

{ "msg": null,"data":

[ { “名称”:“geoit”, “电子邮件”:“rokesh@geoit.in”, “电话”:空, "current_group": "11", “用户组”:

[{ “11”:“父母” } ]

} ],

“错误”:假 }

]

同样在您的代码中,您不需要var jObject = JObject.Parse(readHttpResponse);,因为readHttpResponse 已经是一个JSON 字符串,您可以将其反序列化为一个对象。

【讨论】:

  • 这条线readHttpResponse = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); 给我输出"{\"msg\":null,\"data\":{\"name\":\"geoit\",\"email\":\"rokesh@geoit.in\",\"phone\":null,\"current_group\":\"11\",\"user_groups\":{\"11\":\"Parent\"}},\"error\":false}"
  • 这条线var jObject = JObject.Parse(readHttpResponse);给了我{{ "msg": null, "data": { "name": "geoit", "email": "rokesh@geoit.in", "phone": null, "current_group": "11", "user_groups": { "11": "Parent" } }, "error": false }}
  • 那么如何将外部的{}改为[]...??
  • 尝试直接反序列化readHttpResponse而不是使用JObject.Parse
  • 你的意思是我应该这样给,jsonObject = JsonConvert.DeserializeObject&lt;jsonobjectclass.UserResponse&gt;(readHttpResponse);
【解决方案3】:

为之前的误导性答案道歉。您需要创建数组的对象是响应 JSON 的“数据”属性。您必须从服务器端获取它作为您的 Domainmodal List&lt;User&gt;。你应该从这个fiddle得到更好的理解

readHttpResponse可以

    {
          "msg": null,
          "data": [{
          "name": "geoit",
          "email": "rokesh@geoit.in",
          "phone": null,
          "current_group": "11",
          "user_groups": {
           "11": "Parent"
           }
        }],
        "error": false
   }
 and

readHttpResponse.data 需要是数组

[{
              "name": "geoit",
              "email": "rokesh@geoit.in",
              "phone": null,
              "current_group": "11",
              "user_groups": {
               "11": "Parent"
               }
            }]

【讨论】:

  • 我仅将其作为 {{}} @Jins 接收。因为我无权访问服务器..有没有办法将代码中的外部{}更改为[]??
  • 您没有访问服务器的权限?如果您的预期结果需要数组,您可以建议服务器人员将其设置为数组。
  • 是的,高级开发人员只给了我请求 url 和 JSON 方法。
  • 该响应对象是要在客户端显示的数组或对象集吗?还是它总是需要一个对象
  • 只有一个对象会作为输出
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-18
  • 1970-01-01
  • 1970-01-01
  • 2019-01-02
  • 1970-01-01
相关资源
最近更新 更多