c# - JsonConvert.SerializeObject + TypeConverter = StackOverflowException

标签 c#

我在方法JsonTypeConverter.ConvertTo中收到StackOverflowException 调用 Project.Settings.Default.Save()

我认为这是因为方法 JsonConvert.SerializeObject 检测模型类型上的 typeconverter 并在内部调用它......

正确的写法是什么? (我能想到的唯一方法是将字符串存储在设置中并手动进行序列化/反序列化...)

public class JsonTypeConverter<TModel> : TypeConverter
{
    #region Overrides of TypeConverter

    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return sourceType == typeof(string);
    }

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        return destinationType == typeof(string);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        if (value is string strValue) {
            return JsonConvert.DeserializeObject<TModel>(strValue);
        }

        return base.ConvertFrom(context, culture, value);
    }

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
        if (destinationType == typeof(string) && value is TModel model) {
            return JsonConvert.SerializeObject(model, Formatting.None);
        }

        return base.ConvertTo(context, culture, value, destinationType);
    }

    #endregion
}

namespace Model {

    [TypeConverter(typeof(JsonTypeConverter<DataModel>))]
    [SettingsSerializeAs(SettingsSerializeAs.String)]
    public class DataModel {
        public string Value { get; set; }
    }
}

“Properties/Settings.settings”的内容:

<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="Builder.Properties" GeneratedClassName="Settings">
    <Profiles />
    <Settings>
        <Setting Name="DataSource" Type="Model.DataModel" Scope="User">
            <Value Profile="(Default)" />
        </Setting>
    </Settings>
</SettingsFile>

PS:对此问题标题有什么建议吗?

最佳答案

问题在于,JsonConverter 和 SettingsSerializer 都使用 TypeConverter 属性来告诉它们如何序列化对象。当 JsonConverter 尝试序列化对象时,它最终会通过自定义转换器再次调用自身,并最终导致堆栈溢出。

要在转换器中解决此问题,您必须告诉 JsonConverter 不要使用 TypeConverterAttribute 类型,而只执行默认的对象序列化。这是我发现完成此任务的方法:

public class JsonTypeConverter<TModel> : TypeConverter
{
    /* rest of your class ... */

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        if (value is string strValue)
        {
            return JsonConvert.DeserializeObject<TModel>(strValue, new JsonSerializerSettings
            {
                ContractResolver = new CustomContractResolver(),
            });
        }

        return base.ConvertFrom(context, culture, value);
    }

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
        if (destinationType == typeof(string) && value is TModel model)
        {
            return JsonConvert.SerializeObject(model, new JsonSerializerSettings
            {
                ContractResolver = new CustomContractResolver(),
            });
        }

        return base.ConvertTo(context, culture, value, destinationType);
    }
}     

class CustomContractResolver : DefaultContractResolver
{
    protected override JsonContract CreateContract(Type objectType)
    {
        if (typeof(DataModel).IsAssignableFrom(objectType))
        {
            return this.CreateObjectContract(objectType);
        }
        return base.CreateContract(objectType);
    }
}

关于c# - JsonConvert.SerializeObject + TypeConverter = StackOverflowException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46186666/

相关文章:

c# - ReSharper 7 自动完成在键入 "No suggestions"后错误地显示 "this."

c# - 隐藏继承的 protected 方法

c# - 如何从页面访问用户控件的值?

c# - ASP.NET MVC : How to default to a page given certain condition?

c# - 计算实体的频率和新近度的算法?

c# - 如何提高winform的加载时间?

c# - 如何判断当前应用是否为Medium Trust

c# - 在 C# 中引用一系列标签

c# - 执行两个 IEnumerable 集合的联合类型

c# - 存储静态错误字符串的最佳位置