【问题标题】:Partial deserialization of JSON object by using DataContractJsonSerializer使用 DataContractJsonSerializer 对 JSON 对象进行部分反序列化
【发布时间】:2013-03-16 21:10:41
【问题描述】:

作为来自 Bitbucket REST API 的响应,我得到以下 JSON 对象(简化版):

{
    "repositories": [
        {
            "scm": "hg",
            "has_wiki": false,            
            "language": "c#",
            "slug": "Repo1"
        },
        {
            "scm": "hg",
            "has_wiki": false,            
            "language": "java",
            "slug": "Repo2"
        },
        {
            "scm": "hg",
            "has_wiki": true,            
            "language": "c#",
            "slug": "Repo3"
        }
    ],
    "user": {
        "username": "someuser",
        "first_name": "Some",
        "last_name": "User",
        "display_name": "Some User",
        "is_team": false,
        "avatar": "https://someuseravatar.com",
        "resource_uri": "/1.0/users/someuser"
    }
}

我需要反序列化的这个 JSON 对象的唯一部分是 user 部分。为此,我创建了以下类:

[DataContract(Name="user")]
public class BitbucketUser
{
    [DataMember(Name = "username")]
    public string Username { get; set; }

    [DataMember(Name = "first_name")]
    public string FirstName { get; set; }

    [DataMember(Name = "last_name")]
    public string LastName { get; set; }

    [DataMember(Name = "display_name")]
    public string DisplayName { get; set; }

    [DataMember(Name = "is_team")]
    public bool IsTeam { get; set; }

    [DataMember(Name = "avatar")]
    public string Avatar { get; set; }

    [DataMember(Name = "resource_uri")]
    public string ResourceUri { get; set; }
}

还有一个反序列化json的辅助方法:

public static T Deserialize<T>(string json)
{
    DataContractJsonSerializer deserializer = new DataContractJsonSerializer(typeof(T));
    using (MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(json)))
    {
        T result = (T)deserializer.ReadObject(stream);
        return result;
    }
}

所以,当我尝试使用以下代码反序列化 User 对象时:

User user = JsonHelper.Deserialize<User>(jsonResponse);

然后我得到 user 创建的对象,其中包含 null 的所有属性。我试图找到在类头上使用的正确属性,但结果是一样的。而且我没有使用 Json.NET 库只是为了避免额外的库引用,也没有创建包装类来将该用户对象作为User 类型的属性并将存储库对象作为存储库的数组[ ] 类型。 是否有解决此问题的方法来获取没有空字段的反序列化用户对象?

【问题讨论】:

  • “我没有使用 Json.NET 库只是为了避免额外的库引用” 库引用真的需要避免吗?甚至微软现在也通过 NuGet 分发它的一些库。
  • newtonsoft.com/json/help/html/SerializingJSONFragments.htm 这是使用 newtonsoft.json 的方法(首先在谷歌上得到了这个问题,所以它可能对其他人有用)

标签: c# json deserialization datacontractserializer datacontractjsonserializer


【解决方案1】:

您的代码不起作用,因为您要反序列化的 JSON 对象没有任何 User 属性。反序列化器当然不会尝试查看当前对象的子对象是否匹配。

你应该做的是创建一个代表整个响应对象的类型。如果您对 repositories 部分不感兴趣,请忽略它。

以下代码适用于我:

[DataContract]
public class BitbucketResponse
{
    [DataMember(Name="user")]
    public BitbucketUser User { get; set; }
}

[DataContract]
public class BitbucketUser
{
    [DataMember(Name = "username")]
    public string Username { get; set; }

    // etc.
}

…

var serializer = new DataContractJsonSerializer(typeof(BitbucketResponse));
using (var stream = …)
{
    var response = (BitbucketResponse)serializer.ReadObject(stream);
    var user = response.User;
}

【讨论】:

  • 这是在没有任何第三方库的情况下实现目标的唯一途径。
  • @Arterius 我相信可以使用 JavaScriptSerializer 和不需要第三方库的自定义类型映射器,但这应该可以解决问题
【解决方案2】:

我正在为您编写代码,它将帮助您将对象从 json 反序列化为 yourClassCustomObject。

private async Task<List<BitbucketUser>> MyDeserializerFunAsync()
{
    List<BitbucketUser> book = new List<BitbucketUser>();
    try
    {
       //I am taking my url from appsettings. myKey is my appsetting key. You can write direct your url.
       string url = (string)appSettings["mykey"];
       var request = HttpWebRequest.Create(url) as HttpWebRequest;
       request.Accept = "application/json;odata=verbose";
       var factory = new TaskFactory();
       var task = factory.FromAsync<WebResponse>(request.BeginGetResponse,request.EndGetResponse, null);
       var response = await task;
       Stream responseStream = response.GetResponseStream();
       string data;
       using (var reader = new System.IO.StreamReader(responseStream))
       {
           data = reader.ReadToEnd();
       }
       responseStream.Close();
       DataContractJsonSerializer json = new DataContractJsonSerializer(typeof(List<BitbucketUser>));
       MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(data));
       book = (List<BitbucketUser>)json.ReadObject(ms);
       return book;
   }
} 

上面的代码在我的 wp8 应用程序中运行它更快,你可以试试,它会帮助你。我正在执行异步操作,但您可以使用 BitbucketUser 返回类型创建简单方法。

【讨论】:

  • 但是JSON不是用户数组,所以我认为这段代码行不通。
  • 但是你的 json 遵循 json 的标准格式,对吧?如果是的话,它将起作用。我认为你应该尝试一次。如果此代码不适用于您的情况,您的尝试将有助于纠正自己。
  • 这不是“我的”JSON,我不是提出这个问题的人。但就像我说的,问题中发布的 JSON 不是用户数组,所以我看不出这段代码是如何工作的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多