Элементарно:
https://app.quicktype.io/#r=json2csharp - слева вставляете JSON, справа на выходе получаете готовый класс для парсинга. Удобнейший сервис.
Пример:
{
"greeting": "Welcome to quicktype!",
"instructions": [
"Type or paste JSON here",
"Or choose a sample above",
"quicktype will generate code in your",
"chosen language to parse the sample data"
]
}
namespace QuickType
{
using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using J = Newtonsoft.Json.JsonPropertyAttribute;
using R = Newtonsoft.Json.Required;
using N = Newtonsoft.Json.NullValueHandling;
public partial class Welcome
{
[J("greeting")] public string Greeting { get; set; }
[J("instructions")] public string[] Instructions { get; set; }
}
public partial class Welcome
{
public static Welcome FromJson(string json) => JsonConvert.DeserializeObject<Welcome>(json, QuickType.Converter.Settings);
}
public static class Serialize
{
public static string ToJson(this Welcome self) => JsonConvert.SerializeObject(self, QuickType.Converter.Settings);
}
internal static class Converter
{
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters = {
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
},
};
}
}
Я конвертер выношу в отдельный класс и файл:
using Newtonsoft.Json;
/// <summary>
/// Конвертер JSON
/// </summary>
public static class Converter
{
/// <summary>
/// Настройки конвертации JSON
/// </summary>
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore, // Пропускаем аттрибуты
DateParseHandling = DateParseHandling.None, // Выключаем парсинг дат
NullValueHandling = NullValueHandling.Ignore // Пропускаем пустые значения
// (API-вызов при создании запроса
// сам заполняет нужные поля)
};
}
А парсинг/конвертацию JSON выношу в отдельный класс, от которого уже наследую классы для парсинга данных:
namespace Foo
{
/// <summary>
/// Абстрактный класс - сетевое сообщение: парсинг и
/// генерация JSON из экземпляров наследуемого класса
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class APIMessage<T>
{
/// <summary>
/// Конвертация в JSON
/// </summary>
/// <returns></returns>
public string ToJson()
{
return JsonConvert.SerializeObject(this, Converter.Settings);
}
/// <summary>
/// Парсинг JSON в указанный тип
/// </summary>
/// <param name="json"></param>
/// <returns></returns>
public static T FromJson(string json)
{
try
{
return JsonConvert.DeserializeObject<T>(json, Converter.Settings);
}
catch (Exception e)
{
throw new ServerConnectionException(
"Server response parse error!\nResponse type: <" + typeof(T).FullName
+ ">\nError: " + e.Message
);
}
}
}
}
Как-то так получается:
public class Request : APIMessage<Request>
{
<описание JSON свойств>
}