【问题标题】:Trouble deserializing Json from REST service从 REST 服务反序列化 Json 时遇到问题
【发布时间】:2011-06-30 06:59:39
【问题描述】:

我在反序列化 json 字符串时遇到了困难。

我使用的是 RestSharp api,如果我在请求中指定了 RootElement,效果会很好。然后我转移到 Hammock 来使用 OAuth 功能,但反序列化并不那么容易。

我尝试过使用 DataContractJsonSerializer

DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(List)); var member = (List)ser.ReadObject(response.ContentStream);

但这给了我一个 InvalidCastException。

我试过 JsonConvert

var members = JsonConvert.DeserializeObject<List<Member>>(response.Content);

但出现异常:无法将 JSON 对象反序列化为类型“System.Collections.Generic.List`1[Member]”。

RestSharp 在调用 ExecuteAsync 时轻松解决了这个问题。 Client.ExecuteAsync&lt;List&lt;Member&gt;&gt;(request, (response) =&gt;

我已经束手无策了。 也许我需要一个与 RestSharp 的 RootElement 属性等效的 Hammock?? 只是我的 Json 难以转换?

这是我的成员对象

public partial class Member 
{
    public string State { get; set; }
    public string Joined { get; set; }
    public string lat { get; set; }
    public string Zip { get; set; }
    public string Bio { get; set; }
    public string Name { get; set; }
    public string City { get; set; }
    public string Id { get; set; }
    public string Link { get; set; }
    public string Country { get; set; }
    public string Visited { get; set; }
    public string Photo_url { get; set; }
    public string lon { get; set; }
}

这是 Json:

{
    "results": [
        {
            "zip": "11111",
            "lon": "-122.22000122070312",
            "photo_url": "http: //photos1.aaaaa.com/photos/member/1/6/c/e/member_4469838.jpeg",
            "link": "http: //www.aaaa.com/members/7804365",
            "state": "AA",
            "lang": "en_US",
            "city": "MyCity",
            "country": "us",
            "id": "7804365",
            "visited": "Sat Feb 19 02: 36: 40 EST 2011",
            "topics": [
                {
                    "id": 3340,
                    "urlkey": "pickupsoccer",
                    "name": "Pick-up Soccer"
                },
                {
                    "id": 468,
                    "urlkey": "dads",
                    "name": "Dads"
                },
                {
                    "id": 20557,
                    "urlkey": "coed-soccer",
                    "name": "Coed Soccer"
                },
                {
                    "id": 148421,
                    "urlkey": "windowsphone",
                    "name": "Windows Phone"
                }
            ],
            "joined": "Thu Aug 07 15: 32: 06 EDT 2008",
            "bio": "",
            "name": "aaa bbbb",
            "other_services": {
                "linkedin": {
                    "identifier": "http: //www.bbb.com/in/zzzzz"
                }
            },
            "lat": "47.790000915527344"
        }
    ],
    "meta": {
        "lon": "",
        "count": 1,
        "link": "https: //api.aaaaa.com/members",
        "next": "",
        "total_count": 1,
        "url": "https: //api.aaaaa.com/members?relation=self&order=name&offset=0&format=json&page=800",
        "id": "",
        "title": "Members",
        "updated": "Fri Sep 10 13: 08: 07 EDT 2010",
        "description": "API method",
        "method": "Members",
        "lat": ""
    }
}

更新 为我的 Member 类添加一个封装整个 json 结果的包装器对象解决了这个问题。

public partial class Members
{
    public List<Member> results { get; set; }
    public object meta { get; set; }
}

然后我可以使用以下方法进行反序列化:

var members = JsonConvert.DeserializeObject<Members>(jsonstring);

【问题讨论】:

  • 你能告诉我们没有所有转义双引号的 JSON 数据吗?传输的 JSON 数据希望不包含它们,因为它们不是有效的 JSON 数据,而可能是您的 C# 开发环境的产物。
  • 删除了转义字符并进行了格式化。找到解决方案。感谢您的帮助。

标签: json windows-phone-7 deserialization


【解决方案1】:

尝试使用 Json.net。 我发现 DataContractJsonSerializer 太无能了。 json.net 提供了强大的功能。 可以在这个链接找到

http://json.codeplex.com/

它还包含 .dll 文件和文档。 用于网络文档 http://james.newtonking.com/projects/json/help/

【讨论】:

    【解决方案2】:

    在我们的项目中,我们为此使用 Hammok,您可以尝试像这样修改您的类:

    [DataContract]
    public partial class Member 
    {
       [DataMember(Name="zip")]
       public string Zip { get; set; }
       [DataMember(Name="photo_url")]
       public string Photo_url { get; set; }
       //Etc.
    }
    

    【讨论】:

    • 谢谢,找到了解决方案,但是当我到达那个点时,这将有助于清理我的班级。我不喜欢 api 使用的某些成员名称。
    【解决方案3】:

    您的 JSON 数据中大约存在三个问题区域:

    1. 这里显示的方式,它包含很多在 JSON 中不起作用的开头和结尾的反斜杠和双引号。从您的问题中很难判断这是从 VisualStudio 调试器复制的工件还是数据中的问题。

    2. 传输的数据不是 Member 实例列表,而是包含成员实例列表和一些附加元信息的对象。所以你需要引入一个额外的类,其中包含两个成员 resultsmeta

    3. 您的类 Member 使用以大写字母开头的属性,而 JSON 数据使用所有小写字母。您可以更改属性名称或使用数据 DataMember 注释:

    所以解决方案可能是:

    DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(JsonResponse));
    JsonResponse jsonResponse = (JsonResponse)ser.ReadObject(response.ContentStream);
    

    具有以下类定义:

    [DataContract]
    public partial class Member 
    {
        [DataMember(Name = "state")]
        public string State { get; set; }
        [DataMember(Name = "joined")]
        public string Joined { get; set; }
        [DataMember(Name = "lat")]
        public string Lat { get; set; }
        [DataMember(Name = "zip")]
        public string Zip { get; set; }
        [DataMember(Name = "bio")]
        public string Bio { get; set; }
        [DataMember(Name = "name")]
        public string Name { get; set; }
        [DataMember(Name = "state")]
        public string City { get; set; }
        [DataMember(Name = "city")]
        public string Id { get; set; }
        [DataMember(Name = "link")]
        public string Link { get; set; }
        [DataMember(Name = "country")]
        public string Country { get; set; }
        [DataMember(Name = "visited")]
        public string Visited { get; set; }
        [DataMember(Name = "photo_url")]
        public string PhotoUrl { get; set; }
        [DataMember(Name = "lon")]
        public string Lon { get; set; }
    }
    
    [DataContract]
    public class Meta
    {
        [DataMember(Name = "lon")]
        public string Lon { get; set; }
        [DataMember(Name = "count")]
        public int Count { get; set; }
        [DataMember(Name = "link")]
        public string Link { get; set; }
        [DataMember(Name = "next")]
        public string Next { get; set; }
        [DataMember(Name = "total_count")]
        public int TotalCount { get; set; }
    }
    
    [DataContract]
    public class JsonResponse
    {
        [DataMember(Name = "results")]
        public List<Member> Results { get; set; }
        [DataMember(Name = "meta")]
        public Meta Meta { get; set; }
    }
    

    【讨论】:

    • 1 和 3 无关紧要,但 #2 是正确的!我可以通过指定 RootElement 在 RestSharp 中解决这个问题(因此只有结果被反序列化),但没有考虑更改目标类型以包含结果和元。我能够添加一个包装类(3 行代码)来解决这个问题。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-20
    • 2021-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多