5

As a response from a Bitbucket REST API I'm getting the following JSON object (simplified version):

{
    "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"
    }
}

The only part from this JSON object I need to be deserialized is a user part. For that purposes I created the following class:

[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; }
}

And a helper method to deserialize 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;
    }
}

So, when I'm trying to get deserialized User object by using this code:

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

Then I'm getting user object created containing all properties as null. I have tried to find right attributes to use on class header, but the result is same. And also I'm not using a Json.NET library just to avoid extra library reference as well as I'm not creating wrapper class to hold that user object as property of User type and repositores object as a array of the Repositories[] type. Is there a solution for this issue to get deserialized user object without null fields ?

dbc
  • 104,963
  • 20
  • 228
  • 340
  • “I'm not using a Json.NET library just to avoid extra library reference” Is that library reference really something to avoid? Even Microsoft now distributes some of its libraries through NuGet. – svick Nov 18 '13 at 06:05
  • http://www.newtonsoft.com/json/help/html/SerializingJSONFragments.htm this is how to do it with newtonsoft.json (got this question as first on google, so it might be useful for others) – pajics Aug 13 '16 at 16:54

2 Answers2

4

Your code doesn't work, because the JSON object you're deserializing doesn't have any of the User properties. The deserializer certainly won't try looking into children of the current object to see if something matches.

What you should do is to create a type that represents the whole response object. If you're not interested in the repositories part, then just omit it.

The following code works for me:

[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;
}
svick
  • 236,525
  • 50
  • 385
  • 514
  • This is the only way to achieve the goal without any third party libraries. –  Nov 18 '13 at 20:17
  • @Arterius I believe it's probably possible using JavaScriptSerializer with customt type mappers which wouldn't require third party libraries, but this should do the trick anyway – Grant Thomas Aug 09 '17 at 22:34
0

I am writing a code for you it will help you to deserialize the object from json to 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;
   }
} 

Above code is working in my wp8 application it is faster you can try, it will help you. I am performing asynchronous operation but you can create your simple method with BitbucketUser return type.

Ashish-BeJovial
  • 1,829
  • 3
  • 38
  • 62
  • 1
    But the JSON is not an array of users, so I think this code won't work. – svick Nov 18 '13 at 07:02
  • but your json is following the standard format of json, right ? if yes than it will work. I think you should try once. Your try will help to correct myself, if this code will not work in your case. – Ashish-BeJovial Nov 19 '13 at 07:19
  • 1
    It's not “my” JSON, I'm not the one who asked the question. But like I said, the JSON posted in the question is not an array of users, so I don't see how this code could work. – svick Nov 19 '13 at 10:21