#c# #json
#c# #json
Вопрос:
Все,
Редактировать: Во-первых, спасибо всем за помощь. Во-вторых, я новичок в Stack Overflow, поэтому прошу прощения, если я неправильно добавил это редактирование.
После комментариев и ответов я обновил свою структуру классов до:
класс служб:
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()
{
}
}
}
Класс обслуживания:
using System;
using System.Collections.Generic;
using System.Text;
namespace RTT_API
{
class service
{
public string atocCode{get; set;}
public service()
{
}
}
}
К сожалению, я все еще получаю ту же ошибку. Я думаю, что я все еще не совсем сопоставил свою структуру классов со структурой JSON? К сожалению, я не уверен, в чем моя ошибка. Если это поможет выявить мою ошибку с помощью сравнения, тогда работает следующее:
Класс местоположения
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 locations = JsonSerializer.Deserialize<location>(channelResponse.RootElement.GetProperty("location").GetRawText());
MessageBox.Show(locations.crs);
Оригинальный вопрос:
Мой 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:
servicelist 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()
{
}
}
}
класс служб:
using System;
using System.Collections.Generic;
using System.Text;
namespace RTT_API
{
class services
{
public int serviceUid;
public services()
{
}
}
}
Для десериализации я попытался:
services servicelist = JsonSerializer.Deserialize<services>(channelResponse.RootElement.GetProperty("services").GetRawText());
и
servicelist servicelist = JsonSerializer.Deserialize<servicelist>(channelResponse.RootElement.GetProperty("services").GetRawText());;
В обоих случаях я получаю ‘System.Text.Json.Исключение JSONException’
Я думаю, что существует несоответствие между структурой классов и JSON, но я не могу понять, в чем проблема? Я впервые пытаюсь десериализовать массив.
Спасибо
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()
{
}
}
}
Ответ №1:
Вы можете генерировать точные классы C # в соответствии с вашим JSON, используя инструменты именно для этой цели. Я использовал https://json2csharp.com / , другой — это https://jsonutils.com / — это веб-сервисы, которые не требуют установки на компьютер, другой вариант — создание классов через Visual Studio (с установленными Web Essentials), там вы должны использовать Edit — Paste special — вставить JSON в качестве класса.
Как только у вас есть допустимые классы (я вставил сгенерированные классы ниже), вы можете десериализовать весь корневой объект, а затем получить доступ к любой его части, включая services
часть:
// jsonInputText holds entire JSON string you posted
Root root = JsonSerializer.Deserialize<Root>(jsonInputText);
List<Service> serviceList = root.services;
Сгенерированные классы:
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; }
}
Комментарии:
1. Спасибо за вашу помощь. Я ценю информацию об онлайн-инструментах. Мне было бы интересно узнать, почему мое определение не сработало, если это возможно. Я обновил свое определение serviceUID до общедоступной строки serviceUid { get; set; }, но это все еще не сработало.
2. Нет проблем. Классы должны соответствовать структуре JSON. В строке JSON в свойстве «services» у вас есть массив JSON — это означает, что в свойстве класса «services» должна быть коллекция (Список<>) объектов «service», эти объекты «service» представлены сгенерированным классом Service. Объект Service должен иметь определенные свойства, такие как «locationDetail» и т.д., После последовательной реализации объектов и коллекций ошибок быть не должно — самый простой способ создать правильный класс — использовать некоторые генераторы JSON-to-class . До тех пор, пока структура класса не совпадает, могут возникать ошибки.
3. Еще раз спасибо. Я обновил свой код и вопрос. Я новичок в StackOverflow, так что, надеюсь, это было правильно.
4. Это лучший способ; большое спасибо за советы!
Ответ №2:
Если вам нужно десериализовать только часть вашего json, вы можете использовать JObject
JToken
для этого вспомогательные классы и .
var json = File.ReadAllText("Sample.json");
JObject topLevelObject = JObject.Parse(json);
JToken servicesToken = topLevelObject["services"];
var services = servicesToken.ToObject<List<Service>>();
topLevelObject
Содержит весь json в полуразработанном формате.- Вы можете использовать оператор индексатора для извлечения объекта / массива с помощью одного из ключей верхнего уровня.
- На a
JToken
вы можете вызватьToObject<T>
десериализацию данных в пользовательский класс данных.
Чтобы иметь возможность анализировать ваш json, мне пришлось настроить services
тип, потому W90091
что as serviceUid
не может быть проанализирован как int
. Итак, вот мое Service
определение класса:
public class Service
{
public string ServiceUid;
}
Здесь следует отметить, что в данном случае корпус не имеет значения, поэтому, пожалуйста, используйте camelCasing в ваших доменных моделях, как вы обычно делаете в C #.
Комментарии:
1. Спасибо за совет. Это полезно.
Ответ №3:
Спасибо всем за помощь.
Во-первых, мне пришлось внести несколько изменений в имена классов, поскольку они не соответствовали JSON. Мне также пришлось изменить синтаксис двух команд, которые я подробно описал ниже:
Я изменил определение списка объектов с:
public List<services> service = new List<services>();
Для:
public List<service> destination { get; set; };
и команда десериализации из:
services servicelist = JsonSerializer.Deserialize<services>(channelResponse.RootElement.GetProperty("services").GetRawText());
Для
var servicelist = JsonSerializer.Deserialize<List<service>>(channelResponse.RootElement.GetProperty("services").GetRawText());
Переход с сервисов на var может быть не лучшим решением. Я думаю, что это первое изменение и сопоставление имен классов с JSON, которое в корне устранило проблему.