【问题标题】:Json.NET (JsonConvert.DeserializeObject)Json.NET (JsonConvert.DeserializeObject)
【发布时间】:2016-10-06 04:20:00
【问题描述】:

我正在尝试反序列化来自 facebook/me 的以下 JSON 响应。

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

如何在不创建另一个 DTO 的情况下获取图片/数据属性?

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

DTO:

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

不幸的是,它上面的代码不起作用,因为我缺少额外的 DTO 来表示图片下的 Data 对象。但理想情况下,我不希望另一个 DTO 只用于 Data 并且让 JSON 反序列化知道它可以在 picture.data 下找到图片 DTO 数据!

这可能吗?如果可以,请问如何?

非常感谢!

亲切的问候,尼克

【问题讨论】:

    标签: .net json json.net deserialization


    【解决方案1】:

    您可以使用自定义 JsonConverter 来弥补差距,这样您就不必在模型上创建中间 DTO。这是转换器所需的代码:

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

    要使用转换器,请将[JsonConverter] 属性添加到PictureDto 属性,如下所示:

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

    小提琴:https://dotnetfiddle.net/Tx9FS9

    【讨论】:

    • 很好的答案!非常感谢你!这正是我所追求的!
    • 没问题;很高兴我能帮上忙。
    【解决方案2】:

    如果您使用 Facebook 登录,我建议您使用 Visual Studio 在默认项目中为您生成的 ASP.NET Identity Facebook 提供程序。

    话虽如此,解决问题的更好方法是使用 DTO。它使您的代码类型安全。另一种方法是将对象反序列化为动态对象。您可以在这个很棒的答案中找到更多帮助:Deserialize JSON into C# dynamic object?

    【讨论】:

      【解决方案3】:

      无法直接在数据中映射对象。或者,您可以从 DTO 创建一个测试对象并使用 JsonConvert 对其进行序列化。看看它是否生成与 FB 发送的相同的结构。答案是它不会因为你试图跳过一层。因此,最好为“数据”正确创建。这样,层次结构也得到维护,序列化和反序列化将是安全的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-21
        • 2016-12-17
        相关资源
        最近更新 更多