将结构/类序列化为单个字符串

时间:2019-01-29 21:17:44

标签: c# json asp.net-core serialization

我在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 :(得分:1)

很多时候,当项目更大时,很多类都需要这样做。

我们需要转换才能双向工作。应该使用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.");
        }
    }

最后,将Converter添加到启动类,并在JSON选项中传递

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

                })

注意:请测试代码的性能标记,以查看它是否对性能SLA有影响。

答案 1 :(得分:0)

经过进一步研究,MVC似乎使用JsonConverter属性来序列化JsonResult。下面的代码完成了我想做的事情。

[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());
}