简体   繁体   English

C# JsonSerializer.反序列化数组

[英]C# JsonSerializer.Deserialize array

All,全部,

Edit: Firstly thanks for everyone's help.编辑:首先感谢大家的帮助。 Secondly I'm new to Stack Overflow so apologises if I've added this edit incorrectly.其次,我是 Stack Overflow 的新手,如果我错误地添加了此编辑,我深表歉意。

Following the commments and replies I've updated my class structure to:根据评论和回复,我将 class 结构更新为:

services class:服务 class:

using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Json;

namespace RTT_API
{
    class services
    {
        public List<service> service = new List<service>();

        public services()
        {

        }
    }
}

Service class:服务 class:


using System;
using System.Collections.Generic;
using System.Text;

namespace RTT_API
{
    class service
    {
        public string atocCode{get; set;}

        public service()
        {

        }
    }
}

Unfortunately I'm still getting the same error.不幸的是,我仍然遇到同样的错误。 I think I still haven't quite matched my class structure to the JSON structure?我想我的 class 结构还没有完全匹配到 JSON 结构? Unfortunately I'm not sure where my mistake is.不幸的是,我不确定我的错误在哪里。 If it helps to highlight my mistake using a comparison then the following works:如果它有助于使用比较突出我的错误,那么以下工作:

Location class位置 class

using System; 
using System.Collections.Generic;
using System.Text;

namespace RTT_API
{
    class location
    {
        public string name { get; set; }
        public string crs { get; set; }

        public location()
        {
            
        }
    }
}

Location deserilisation command and test output:定位反序列化命令和测试 output:

location locations = JsonSerializer.Deserialize<location>(channelResponse.RootElement.GetProperty("location").GetRawText());

MessageBox.Show(locations.crs);

Original question:原始问题:

My JSON is as follows:我的 JSON 如下:

{
   "location": {
       "name": "Bournemouth",
       "crs": "BMH",
       "tiploc": "BOMO"
   },
   "filter": null,
   "services": [
       {
           "locationDetail": {
               "realtimeActivated": true,
               "tiploc": "BOMO",
               "crs": "BMH",
               "description": "Bournemouth",
               "wttBookedArrival": "011630",
               "wttBookedDeparture": "011830",
               "gbttBookedArrival": "0117",
               "gbttBookedDeparture": "0118",
               "origin": [
                   {
                       "tiploc": "WATRLMN",
                       "description": "London Waterloo",
                       "workingTime": "230500",
                       "publicTime": "2305"
                   }
               ],
               "destination": [
                   {
                       "tiploc": "POOLE",
                       "description": "Poole",
                       "workingTime": "013000",
                       "publicTime": "0130"
                   }
               ],
               "isCall": true,
               "isPublicCall": true,
               "realtimeArrival": "0114",
               "realtimeArrivalActual": false,
               "realtimeDeparture": "0118",
               "realtimeDepartureActual": false,
               "platform": "3",
               "platformConfirmed": false,
               "platformChanged": false,
               "displayAs": "CALL"
           },
           "serviceUid": "W90091",
           "runDate": "2013-06-11",
           "trainIdentity": "1B77",
           "runningIdentity": "1B77",
           "atocCode": "SW",
           "atocName": "South West Trains",
           "serviceType": "train",
           "isPassenger": true
       }
   ]
}

My class structure is as follows:我的 class 结构如下:

servicelist class:服务清单 class:

using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Json;

namespace RTT_API
{
    class servicelist
    {
        public List<services> service = new List<services>();

        public servicelist()
        {

        }
    }
}

services class:服务 class:

using System;
using System.Collections.Generic;
using System.Text;

namespace RTT_API
{
    class services
    {
        public int serviceUid;

        public services()
        {

        }

    }
}

For deserialisation I have tried:对于反序列化,我尝试过:

services servicelist = JsonSerializer.Deserialize<services>(channelResponse.RootElement.GetProperty("services").GetRawText());

and

servicelist servicelist = JsonSerializer.Deserialize<servicelist>(channelResponse.RootElement.GetProperty("services").GetRawText());;

In both cases I get 'System.Text.Json.JsonException'在这两种情况下,我都会得到“System.Text.Json.JsonException”

I think there is a mismatch betwee the class structure and the JSON but I can't work what the problem is?我认为 class 结构和 JSON 之间存在不匹配,但我无法解决问题是什么? It's the first time I've tried to desarialise an array.这是我第一次尝试对数组进行反序列化。

Thanks谢谢

using System; 
using System.Collections.Generic;
using System.Text;

namespace RTT_API
{
    class location
    {
        public string name { get; set; }
        public string crs { get; set; }

        public location()
        {
            
        }
    }
}

You can generate exact C# classes according to your JSON using tools for exactly that purpose.您可以根据您的 JSON 使用工具生成精确的 C# 类。 I used https://json2csharp.com/ , another is https://jsonutils.com/ - these are web services and don't require installation on computer, another option is generating classes through Visual Studio (with Web Essentials installed), there you would use Edit - Paste special - paste JSON as class. I used https://json2csharp.com/ , another is https://jsonutils.com/ - these are web services and don't require installation on computer, another option is generating classes through Visual Studio (with Web Essentials installed),在那里你会使用编辑 - 特殊粘贴 - 将 JSON 粘贴为 class。

Once you have the valid classes (I pasted generated classes below) you can deserialize entire Root object and then access any part of it, including services part:一旦有了有效的类(我在下面粘贴了生成的类),您就可以反序列化整个 Root object,然后访问它的任何部分,包括services部分:

    // jsonInputText holds entire JSON string you posted
    Root root = JsonSerializer.Deserialize<Root>(jsonInputText);
    List<Service> serviceList = root.services;

Generated classes:生成的类:

public class Location
{
    public string name { get; set; }
    public string crs { get; set; }
    public string tiploc { get; set; }
}

public class Origin
{
    public string tiploc { get; set; }
    public string description { get; set; }
    public string workingTime { get; set; }
    public string publicTime { get; set; }
}

public class Destination
{
    public string tiploc { get; set; }
    public string description { get; set; }
    public string workingTime { get; set; }
    public string publicTime { get; set; }
}

public class LocationDetail
{
    public bool realtimeActivated { get; set; }
    public string tiploc { get; set; }
    public string crs { get; set; }
    public string description { get; set; }
    public string wttBookedArrival { get; set; }
    public string wttBookedDeparture { get; set; }
    public string gbttBookedArrival { get; set; }
    public string gbttBookedDeparture { get; set; }
    public List<Origin> origin { get; set; }
    public List<Destination> destination { get; set; }
    public bool isCall { get; set; }
    public bool isPublicCall { get; set; }
    public string realtimeArrival { get; set; }
    public bool realtimeArrivalActual { get; set; }
    public string realtimeDeparture { get; set; }
    public bool realtimeDepartureActual { get; set; }
    public string platform { get; set; }
    public bool platformConfirmed { get; set; }
    public bool platformChanged { get; set; }
    public string displayAs { get; set; }
}

public class Service
{
    public LocationDetail locationDetail { get; set; }
    public string serviceUid { get; set; }
    public string runDate { get; set; }
    public string trainIdentity { get; set; }
    public string runningIdentity { get; set; }
    public string atocCode { get; set; }
    public string atocName { get; set; }
    public string serviceType { get; set; }
    public bool isPassenger { get; set; }
}

public class Root
{
    public Location location { get; set; }
    public object filter { get; set; }
    public List<Service> services { get; set; }
}

If you need to deserialize only just a part of your json then you can use the JObject and JToken helper classes for that.如果您只需要反序列化 json 的一部分,那么您可以使用JObjectJToken辅助类。

var json = File.ReadAllText("Sample.json");
JObject topLevelObject = JObject.Parse(json);
JToken servicesToken = topLevelObject["services"];
var services = servicesToken.ToObject<List<Service>>();
  • The topLevelObject contains the whole json in a semi-parsed format. topLevelObject以半解析格式包含整个 json。
  • You can use the indexer operator to retrieve an object / array by using one of the top level keys.您可以使用索引器运算符通过使用顶级键之一来检索 object / 数组。
  • On a JToken you can call the ToObject<T> to deserialize the data into a custom data class.JToken ,您可以调用ToObject<T>将数据反序列化为自定义数据 class。

In order to be able to parse your json I had to adjust the services type because the W90091 as serviceUid can't be parsed as int .为了能够解析您的 json 我不得不调整services类型,因为无法将W90091作为serviceUid解析为int So here is my Service class definition:所以这是我的Service class 定义:

public class Service
{
    public string ServiceUid;
}

One thing to note here is that casing does not matter in this case so please use CamelCasing in your domain models as you would normally do in C#.这里要注意的一件事是,在这种情况下,大小写无关紧要,因此请在您的域模型中使用 CamelCasing,就像您通常在 C# 中所做的那样。

Thanks for everyone's help.感谢大家的帮助。

Firstly I had to make a few changes to the class names as they didn't match the JSON.首先,我必须对 class 名称进行一些更改,因为它们与 JSON 不匹配。 I also had to change the syntax of two commands which I've detailed below:我还必须更改下面详述的两个命令的语法:

I changed the definition of the list of objects from:我将对象列表的定义从:

public List<services> service = new List<services>();

to:至:

public List<service> destination { get; set; };

and deserilisation command from:和去序列化命令来自:

services servicelist = JsonSerializer.Deserialize<services>(channelResponse.RootElement.GetProperty("services").GetRawText());

to

var servicelist = JsonSerializer.Deserialize<List<service>>(channelResponse.RootElement.GetProperty("services").GetRawText());

The change from services to var might not be the best solution.从 services 更改为 var 可能不是最好的解决方案。 I think it's the first change, and matching the class names to the JSON, that fundamentally fixed the issue.我认为这是第一个更改,将 class 名称与 JSON 匹配,从根本上解决了这个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM