Сериализация структуры / класса в виде одной строки - PullRequest
0 голосов
/ 30 января 2019

У меня есть структура, которую я использую в своих ViewModels, чтобы упростить способ их автоматической сериализации.Я хочу, чтобы сериализация просто вызвать метод .ToString().В настоящее время, когда он сериализован в JSON, он превращается в: "{}".Вот мой класс Date:

public struct Date
{
    private DateTime _date;

    public Date(DateTime date)
    {
        _date = date;
    }

    public static implicit operator Date(DateTime date) => new Date(date);

    public override string ToString() => _date.ToString("yyyy-MM-dd");
}

Я думал, что может быть какой-то атрибут, которым я могу украсить структуру, или, возможно, какой-то интерфейс, который я могу реализовать, но, похоже, это не помогает.

Ответы [ 2 ]

0 голосов
/ 30 января 2019

Много раз, это требуется во многих классах, когда проект больше.

Нам нужно, чтобы преобразование работало в обе стороны.Класс должен быть сериализован с использованием метода ToString(), а класс должен быть десериализован из String.Мы используем следующее соглашение.

Определите интерфейсы маркера, чтобы классы могли четко придерживаться контракта, чтобы они поддерживали сериализацию с использованием метода ToString, а также поддерживают десериализацию из строки в экземпляр объекта.

    /// <summary>
    /// Interface to convert string to a type T
    /// </summary>
    public interface IStringToTypeConverter<out T>
    {
        T ConvertToType(string stringToConvertFrom);

    }

    /// <summary>
    /// Marker Interface to let Serialization/Deserialization work on the ToString Method of the class, Rather than
    /// calling on the Instance properties
    /// </summary>
    public interface ITypeToStringConverter
    {
    }

Затем определите универсальный конвертер, который будет выполнять преобразование (сериализацию / десериализацию) для класса, который реализует указанные выше интерфейсы.

    public class ToStringJsonConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {

            var isTypeImplementStringToTypeConverter = objectType.GetInterfaces().Any(x =>
                x == typeof(ITypeToStringConverter) ||
                (x.IsGenericType &&
                x.GetGenericTypeDefinition() == typeof(IStringToTypeConverter<>)));

            return isTypeImplementStringToTypeConverter;
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            writer.WriteValue(value.ToString());
        }

        public override bool CanRead
        {
            get { return true; }
        }

        public override bool CanWrite
        {
            get { return true; }
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            // Load the JSON for the Result into a JObject

            var stringValue = reader.Value.ToString();

            if (string.IsNullOrWhiteSpace(stringValue))
            {
                var jObject = JObject.Load(reader);
                stringValue = jObject.ToString();

            }

            MethodInfo parse = objectType.GetMethod("ConvertToType");
            if (parse != null)
            {
                var destinationObject = Activator.CreateInstance(objectType,stringValue);
                return parse.Invoke(destinationObject, new object[] { stringValue });
            }

            throw new JsonException($"The {objectType.Name} type does not have a public ConvertToType(string) method.");
        }
    }

Наконец, добавьте конвертер в класс запуска, передав его в параметрах JSON

services.AddMvc().AddJsonOptions(options =>
                {
                    options.SerializerSettings.Converters.Add(new ToStringJsonConverter());

                })

Примечание. Пожалуйста, проверьте показатели производительности для своего кода, чтобы увидеть, влияет ли это на вашу SLA производительности.

0 голосов
/ 30 января 2019

После некоторых дальнейших исследований похоже, что MVC использует атрибут JsonConverter для сериализации JsonResult s.Код ниже завершил то, что я пытался сделать.

[JsonConverter(typeof(DateToString))]
public struct Date
{
    private DateTime _date;

    public Date(DateTime date)
    {
        _date = date;
    }

    public static implicit operator Date(DateTime date) => new Date(date);

    public override string ToString() => _date.ToString("yyyy-MM-dd");
}

public class DateToString : JsonConverter
{
    public override bool CanConvert(Type objectType) => objectType == typeof(Date);
    public override bool CanRead => false;
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        => throw new NotImplementedException();

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) =>
        writer.WriteValue(value.ToString());
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...