0

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

Brian Rogers
  • 125,747
  • 31
  • 299
  • 300
Nik
  • 2,863
  • 6
  • 24
  • 29

3 Answers3

1

if you're using Facebook login I recommend you use the ASP.NET Identity Facebook providers that Visual Studio generates for you in a default project.

Having said that, the better approach to solve your problem is to use a DTO. It keeps your code type safe. The other approach is to deserialize object into a Dynamic object. You can find further help at this great answer: Deserialize JSON into C# dynamic object?

Community
  • 1
  • 1
Ali Kareem Raja
  • 566
  • 1
  • 7
  • 21
1

There's no way to map objects in data directly. Alternatively you can create a test object from DTO and serialize it using JsonConvert. See if it generates same structure as sent by FB. Answer is it won't because you're trying to skip one layer. So it's better if you create properly for "data". That way hierarchy is also maintained and serialization and deserialization will be safe.

Pratik Gaikwad
  • 1,526
  • 2
  • 21
  • 44
1

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

Fiddle: https://dotnetfiddle.net/Tx9FS9

Brian Rogers
  • 125,747
  • 31
  • 299
  • 300