【问题标题】:How to deserialize specific element with DataContractJsonSerializer如何使用 DataContractJsonSerializer 反序列化特定元素
【发布时间】:2016-02-07 01:51:11
【问题描述】:

我正在尝试使用 DataContractJsonSerializer 类反序列化 json 数据。一个问题是如何设置根元素?

我的 json 数据在这里。

{
   "delete":{
      "status":{
         "id":696142765093072896,
         "id_str":"696142765093072896",
         "user_id":2223183576,
         "user_id_str":"2223183576"
      },
      "timestamp_ms":"1454808363540"
   }
}

我写了这样的反序列化类。但它不起作用。我的Status 始终为空。

[DataContract(Name="delete")]
public class Delete
{
    [DataMember(Name="status")]
    public DeletedStatus Status { get; set; }
}

public class DeletedStatus
{
    [DataMember(Name = "id")]
    public long Id { get; set; }
    [DataMember(Name = "user_id")]
    public long UserId { get; set; }
}

如何从特定元素开始解析 json?

【问题讨论】:

  • 发生反序列化时,属性名称和对象结构必须逐字符匹配目标类型。如果有拼写错误、数据结构不正确等,那么反序列化将不起作用。我相信您的反序列化失败的原因是您的 JSON 与目标类型存在许多不匹配。

标签: c# json deserialization datacontractserializer


【解决方案1】:

根据我从 JSON 中得知的信息,反序列化似乎失败了,因为对象的根属性是“删除”属性。我不相信这将与 DataContractJsonSerializer 一起使用,因为给定类型与 Delete 类型不匹配。另一个可能的问题是我看到 DeleteStatus 类缺少 [DataContract] 属性。

长话短说,没有简单的方法可以做你想做的事。话虽如此,反序列化 JSON 有一种简短而甜蜜的方法,而不会增加很多额外的麻烦。我建议创建一个表示当前状态下 JSON 的数据类型,然后反序列化为该类型。

我编写了一个可以从 Visual Studio 测试项目运行的单元测试。我希望这会有所帮助。

JsonDeserializationTests.cs

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Runtime.Serialization.Json;
using System.IO;

namespace SerializationTests {
    [TestClass]
    public class JsonDeserializationTests {
        [TestMethod]
        public void Deserialize_Delete_Type_Success() {
            string json = string.Empty;
            //Set the DataContractJsonSerializer target type to our wrapper type.
            var ser = new DataContractJsonSerializer(typeof(DeleteWrapperJsonResult));
            //Create an instance of the wrapper that reflects the JSON  that you gave.
            //This will help me mock the data that you gave.
            var deleteWrapper = new DeleteWrapperJsonResult {
                delete = new DeleteJsonResult {
                    status = new DeletedStatusJsonResult {
                        id = 696142765093072896,
                        user_id = 2223183576
                    }
                }
            };
            //Convert the mock data to JSON to reflect the JSON that you gave.
            using (var serStream = new MemoryStream()) {
                using (var sr = new StreamReader(serStream)) {
                    ser.WriteObject(serStream, deleteWrapper);
                    serStream.Position = 0;
                    json = sr.ReadToEnd(); //Set the JSON string here.
                    //Output "{\"delete\":{\"status\":{\"id\":696142765093072896,\"id_str\":\"696142765093072896\",\"user_id\":2223183576,\"user_id_str\":\"2223183576\"}}}"
                }
            }
            //Prepeare to Deserialize the JSON.
            var deserialized = default(DeleteWrapperJsonResult);
            using (var deserStream = new MemoryStream()) {
                using (var sw = new StreamWriter(deserStream)) {
                    sw.Write(json); //Write the JSON to the MemoryStream
                    sw.Flush();
                    deserStream.Seek(0, SeekOrigin.Begin);
                    //Deserialize the JSON into an instance of our wrapper class.
                    //This works because of the structure of the JSON.
                    deserialized = (DeleteWrapperJsonResult)ser.ReadObject(deserStream);
                }
            }
            //Initialize the actual Delete instanace with what was deserialized.
            var delete = new Delete {
                Status = new DeletedStatus {
                    //These values were populated with the JSON values.
                    UserId = deserialized.delete.status.user_id,
                    Id = deserialized.delete.status.id
                }
            };
            //Write asserts around what was given and check for equality.
            Assert.AreEqual(delete.Status.UserId, deleteWrapper.delete.status.user_id);
            Assert.AreEqual(delete.Status.Id, deleteWrapper.delete.status.id);
            //Test Passes for Me
        }
    }
}

删除.cs

using System.Runtime.Serialization;

namespace SerializationTests {
    [DataContract]
    [KnownType(typeof(Delete))]
    public class Delete {
        [DataMember]
        public DeletedStatus Status { get; set; }
    }

    [DataContract]
    [KnownType(typeof(DeletedStatus))]
    public class DeletedStatus {
        [DataMember]
        public long Id { get; set; }
        [DataMember]
        public long UserId { get; set; }

    }

    /**************************************************************
     These types below are what comprise our wrapper class so that we can
     use the JSON in its current state. The wrapper classes have properties that
     are synonymous with the JSON properties.
     **************************************************************/
    //This structure represents the object nesting as it appears currently in your example.
    [DataContract]
    [KnownType(typeof(DeleteJsonResult))]
    public class DeleteWrapperJsonResult {
        [DataMember]
        public DeleteJsonResult delete { get; set; }
    }

    [DataContract]
    [KnownType(typeof(DeleteJsonResult))]
    public class DeleteJsonResult {
        [DataMember]
        public DeletedStatusJsonResult status { get; set; }
    }

    [DataContract]
    [KnownType(typeof(DeletedStatusJsonResult))]
    public class DeletedStatusJsonResult {
        [DataMember]
        public long id { get; set; }
        [DataMember]
        public string id_str {
            get {
                return id.ToString();
            }
            set {
                return;
            }
        }
        [DataMember]
        public long user_id { get; set; }
        [DataMember]
        public string user_id_str {
            get {
                return user_id.ToString();
            }
            set {
                return;
            }
        }
    }
}

截至撰写本文时,我的单元测试已通过!如果我能提供进一步的帮助,请告诉我。

【讨论】:

  • 我像你一样写了包装类。非常感谢:D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-07
  • 1970-01-01
  • 1970-01-01
  • 2010-10-10
  • 1970-01-01
相关资源
最近更新 更多