user2118781 user2118781 - 2 months ago 12
JSON Question

Json.NET (JsonConvert.DeserializeObject)

I am trying to deserialise the following JSON response from facebook/me.

{
"id": "53234...",
"first_name": "Nik",
"last_name": "Westfield",
"email": "nik@youremail.com",
"picture": {
"data": {
"height": 720,
"is_silhouette": false,
"url": "https://scontent.xx.fbcdn.net/v/t1.0-1/p720x720/3221.....",
"width": 720
}
}
}


How can I get the picture/data properties without creating another DTO?

var me = await Task.Run(() => JsonConvert.DeserializeObject<FacebookMeDto>(json)).ConfigureAwait(false);


DTOs:

public class FacebookMeDto
{
[JsonProperty("id")]
public string Id { get; set; }

...

[JsonProperty("picture")]
public FacebookPictureDto PictureDto { get; set; }
}

public class FacebookPictureDto
{
[JsonProperty("height")]
public int Height { get; set; }

...

[JsonProperty("url")]
public string Url { get; set; }
}


Unfortunately the code above it not working as I am missing the extra DTO to represent the Data object under picture. But ideally I don't want another DTO just for Data and have the JSON deserialise know that it can find the picture-DTO data under picture.data!

Is this possible and if so how please?

Thanks a lot!

Kind regards, Nik

Answer

You can use a custom JsonConverter to bridge the gap so you don't have to create an intermediate DTO on your model. Here is the code you would need for the converter:

public class FacebookPictureDtoConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(FacebookPictureDto);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject obj = JObject.Load(reader);
        FacebookPictureDto dto = new FacebookPictureDto();
        serializer.Populate(obj["data"].CreateReader(), dto);
        return dto;
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

To use the converter, add a [JsonConverter] attribute to the PictureDto property like this:

public class FacebookMeDto
{
    [JsonProperty("picture")]
    [JsonConverter(typeof(FacebookPictureDtoConverter))]
    public FacebookPictureDto PictureDto { get; set; }
}