【问题标题】:deserializing Json data which contain an array in c#在c#中反序列化包含数组的Json数据
【发布时间】:2019-01-19 21:47:33
【问题描述】:

我在反序列化 Json 消息中的另一个列表时遇到问题。 我的代码可以很好地读取 Project、Ref、Latitude 等数据... 我也尝试了这两种方法:列表和数组。

例如我的 JSON 消息:

[{
    "Project":"example", 
    "Ref":"001BC50C70000A21", 
    "Latitude":43.643166, 
    "Longitude":1.454769, 
    "ParkList": [{
        "Id":"001BC50C70000A21P1", 
        "State":1, 
        "DateTime":"2018-02-15T08:07:18.987Z"
    }, {
        "Id":"001BC50C70000A21P2",
        "State":1,
        "DateTime":"2018-02-15T08:11:41.824Z"
    }]
}]

我的班级:

[DataContract]
public class KMessage
{
    private string ProjectField;
    private string RefField;
    private float LatitudeField;
    private float LongitudeField;
    public List<TParkList> ParkList { get; set; }

    [DataMember]
    public string Project
    {
        get
        {
            return this.ProjectField;
        }
        set
        {
            this.ProjectField = value;
        }
    }
    [DataMember]
    public string Ref
    {
        get
        {
            return this.RefField;
        }
        set
        {
            this.RefField = value;
        }
    }
    [DataMember]
    public float Latitude
    {
        get
        {
            return this.LatitudeField;
        }
        set
        {
            this.LatitudeField = value;
        }
    }
    [DataMember]
    public float Longitude
    {
        get
        {
            return this.LongitudeField;
        }
        set
        {
            this.LongitudeField = value;
        }
    }
}

[DataContract]
public class TParkList
{
    private string IdField;
    private int StateField;
    private string DateTimeField;

    [DataMember]
    public string Id
    {
        get
        {
            return this.IdField;
        }
        set
        {
            this.IdField = value;
        }
    }
    [DataMember]
    public int State
    {
        get
        {
            return this.StateField;
        }
        set
        {
            this.StateField = value;
        }
    }
    [DataMember]
    public string DateTime
    {
        get
        {
            return this.DateTimeField;
        }
        set
        {
            this.DateTimeField = value;
        }
    }
}

以及测试的主要代码。所以“kmsg.ParkList”的列表是空的:

  [ServiceContract]
    public interface IKService
    {
        [DataContractFormat] 
        [OperationContract] 
        [WebInvoke(
             Method = "POST",
             BodyStyle = WebMessageBodyStyle.Bare,
             RequestFormat = WebMessageFormat.Json,
             ResponseFormat = WebMessageFormat.Json,
             UriTemplate = "/state")]
        void Service(Stream KStream); 
    }

    public class KService : IKService
    {
        public void Service(Stream KStream)
        {
            try
            {
                if (KStream == null)
                {
                    MessageBox.Show("WebService message is NULL");
                }

                else
                {
                    DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(List<KMessage>));
                    var obj = (List<KMessage>)serializer.ReadObject(KStream);

                    foreach (KMessage kmsg in obj)
                    {
                        MessageBox.Show("Project", kmsg.Project);
                        foreach (var pklist in kmsg.ParkList)
                        {
                            MessageBox.Show("List - Id", pklist.Id.ToString());
                        }
                    }
                }
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
    }

感谢您的帮助。

【问题讨论】:

标签: c# json list serialization


【解决方案1】:

您没有在KMessage 中将您的列表声明为数据合同的成员。 这意味着它不可序列化。

尝试将其添加到您的班级KMessage

[DataMember]
public List<TParkList> ParkList
    {
        get
        {
            return this.ParkList;
        }
        set
        {
            this.ParkList = value;
        }
    }

【讨论】:

  • 我尝试在 KMessage 中声明此列表,但也不起作用。我的 kmsg.ParkList 又是一个空数组。
  • @PouLpeX 我更新了我的答案,并且您的 json 字符串代码也可以正常工作。请检查一下
  • 如图所示,这将导致无限递归。但是[DataMember] 在自动实现的属性上工作得很好,所以不需要切换到显式实现。
【解决方案2】:

您可以使用 Visual Studio 提供的函数将您的 json 转换为模型类

转到:编辑 -> 选择性粘贴 -> 将 JSON 粘贴为类

此功能创建的模型类将解决您的问题

我使用了这个特性并为你创建了模型类。

        //Use respective attributes 
        public class KMessage
        {
            public string Project { get; set; }
            public string Ref { get; set; }
            public float Latitude { get; set; }
            public float Longitude { get; set; }
            //I guess here is the problem, instead of array you can use list
            public Parklist[] ParkList { get; set; } 
        }

        public class Parklist
        {
            public string Id { get; set; }
            public int State { get; set; }
            public DateTime DateTime { get; set; }
        }

我猜你在反序列化时遗漏了一些东西,这里是你如何反序列化你的 json 字符串。我正在使用Newtonsoft.Json 库。

string jsonString = "[{\"Project\":\"example\", \"Ref\":\"001BC50C70000A21\", \"Latitude\":43.643166, \"Longitude\":1.454769, \"ParkList\": [{\"Id\":\"001BC50C70000A21P1\", \"State\":1, \"DateTime\":\"2018-02-15T08:07:18.987Z\"}, {\"Id\":\"001BC50C70000A21P2\",\"State\":1,\"DateTime\":\"2018-02-15T08:11:41.824Z\"}]}]";

//You used [square brackets] at first, so we need to deserialize with list
List<KMessage> kMsg = JsonConvert.DeserializeObject<List<KMessage>>(jsonString);
foreach (Parklist item in kMsg[0].ParkList)
     {
         Console.WriteLine("Id: " + item.Id + " State: " + item.State + " DateTime: " + item.DateTime);
     }

Output:

Id: 001BC50C70000A21P1 State: 1 DateTime: 2/15/2018 8:07:18 AM
Id: 001BC50C70000A21P2 State: 1 DateTime: 2/15/2018 8:11:41 AM

概念证明:.net Fiddler

【讨论】:

  • 感谢您向我展示了一个我不知道的好功能。
  • 我通过这种方法开始我的班级建设。我又试了一次,问题还是一样的。我只是添加 [DataContract] 和 [DataMember] (没有,代码不要在第一个 foreach 中输入)并且它们再次使用相同的模型类,但问题是一样的。
  • 在第二个foreach中,程序进入catch,因为parklist为空
  • 我正在使用你的库 Newtonsoft.Json。我首先在我的第一个 foreach 中尝试您的代码,所以当我发布 Json 消息时,我会在您的代码中输入测试 ParkList 类的代码作为开始。但它们也不起作用。 jsonString 没问题,并且对于 System.Collections.Generic.List 类型,kMsg 为 null
  • 我不明白为什么,在第一个 foreach 循环中,每个字段都有数据,而 ParkList 数组为空。所以当我尝试反序列化对象时,我会反序列化空对象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-27
  • 2015-06-11
  • 2017-01-18
  • 2015-05-14
  • 2022-10-14
  • 1970-01-01
相关资源
最近更新 更多