如何使用 DataContractJsonSerializer 反序列化特定元素

本文关键字:元素 反序列化 何使用 DataContractJsonSerializer | 更新日期: 2023-09-27 18:33:35

我正在尝试使用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?

如何使用 DataContractJsonSerializer 反序列化特定元素

根据我从 JSON 中可以看出的情况,反序列化似乎失败,因为对象的根属性是"删除"属性。我不相信这将适用于DataContractJsonSerializer,因为给定的类型与Delete类型不匹配。另一个可能的问题是我看到 DeleteStatus 类缺少 [DataContract] 属性。

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

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

Json反序列化测试.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;
            }
        }
    }
}

截至撰写本文时,我的单元测试已通过!让我知道我是否可以进一步提供帮助。