首页 > 解决方案 > Json.NET:序列化图表系列只返回“类型名称”

问题描述

我正在尝试使用 NewtonSoft.Json 序列化 System.Windows.Forms.DataVisualization.Charting.Series,我得到的只是系列的名称及其类型。我正在尝试获取该系列的所有属性,以便保存人们设置的系列设置。

我对序列化很陌生,但是我在其他对象上取得了一些成功,所以我不确定这里发生了什么。这是我所做的(例如):

JsonConvert.SerializeObject(new Series("TestName"), Formatting.Indented);

回报: "Series-TestName"

我期待更多类似的东西

{
  "AxisLabel": "",
  "BackGradientStyle": None,
  "BackHatchStyle": None
...
}

标签: serializationjson.net

解决方案


感谢@dbc 将我指向此处NoTypeConverterJsonConverter<T>讨论的内容,我能够解决我的问题。

我制作了一个修改版本,NoTypeConverterJsonConverter<T>取而代之的是一个类型列表来应用 NoType 转换:

public class NoTypeConverterJsonConverter : JsonConverter
{
    private NoTypeConverterContractResolver Resolver = new NoTypeConverterContractResolver();

    /// <summary>
    /// The types where the default typeconverter will not be used
    /// </summary>
    public List<Type> TypesToOverride
    {
        get { return Resolver.DefaultedTypes; }
        set { Resolver.DefaultedTypes = value; }
    }

    private class NoTypeConverterContractResolver : DefaultContractResolver
    {
        /// <summary>
        /// The types where the default typeconverter will not be used
        /// </summary>
        public List<Type> DefaultedTypes = new List<Type>();

        protected override JsonContract CreateContract(Type objectType)
        {
            // if its in the listed types
            if (DefaultedTypes.Any(t => t.IsAssignableFrom(objectType)))
            {
                // create a default contract
                JsonObjectContract contract = base.CreateObjectContract(objectType);
                // Null out the converter to not use the default typeconverter.
                contract.Converter = null; 
                return contract;
            }
            // if it decends from a list
            else if (typeof(IList<>).IsAssignableFrom(objectType))
            {
                // create a contract from the object, avoiding any presets(?)
                JsonObjectContract contract = this.CreateObjectContract(typeof(IList<>));
                //contract.Converter = null; // Also null out the converter to prevent infinite recursion.
                return contract;
            }

            try
            {
                // use default contract creator
                return base.CreateContract(objectType);
            }
            catch (Exception ex)
            {
                // see if it can be treated as a list
                if (typeof(IList<>).IsAssignableFrom(objectType))
                {
                    // create a contract from the object, avoiding any presets(?)
                    JsonObjectContract contract = this.CreateObjectContract(typeof(IList<>));
                    //contract.Converter = null; // Also null out the converter to prevent infinite recursion.
                    return contract;
                }

                throw ex;
            }
                    
        }

        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
        {
            JsonProperty property = base.CreateProperty(member, memberSerialization);

            return property;
        }
    }

    /// <summary>
    /// Default Constructor
    /// </summary>
    /// <param name="skippedTypes"></param>
    public NoTypeConverterJsonConverter(List<Type> skippedTypes = null)
    {
        if (skippedTypes != null)
        {
            TypesToOverride = skippedTypes;
        }
    }

    public override bool CanConvert(Type objectType)
    {
        return TypesToOverride.Any(t => t.IsAssignableFrom(objectType));
    }

    public override object ReadJson(
        JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        return JsonSerializer.CreateDefault(
            new JsonSerializerSettings { ContractResolver = Resolver }
            ).Deserialize(reader, objectType);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        JsonSerializer.CreateDefault(
            new JsonSerializerSettings { ContractResolver = Resolver }
            ).Serialize(writer, value);
    }
}

我还发现 Collections likeDataPointCollection往往被处理得很差,只返回计数,所以我添加了 IList 部分:

// see if it can be treated as a list
if (typeof(IList<>).IsAssignableFrom(objectType))
{
    // create a contract from the object, avoiding any presets(?)
    JsonObjectContract contract = this.CreateObjectContract(typeof(IList<>));
    //contract.Converter = null; // Also null out the converter to prevent infinite recursion.
    return contract;
}

然后像这样使用代码:

// The types to not use the default typeconverter
List<Type> skippedTypes = new List<Type>()
{
    typeof(DataPoint),
    typeof(DataPointCustomProperties),
    typeof(SmartLabelStyle)
};

// create converter
NoTypeConverterJsonConverter converter = new NoTypeConverterJsonConverter(skippedTypes);

// use the converter to serialize a series
string seriesstr = JsonConvert.SerializeObject(series, Formatting.Indented, 
    new JsonSerializerSettings()
    {
        Converters = new List<JsonConverter> { converter }
    });

// deserialise using the same converter
Series series2 = JsonConvert.DeserializeObject<Series>(seriesstr, new JsonSerializerSettings()
{
    Converters = new List<JsonConverter> { converter }
});

实际上,只需将任何给您带来麻烦的类型添加到该列表中,它通常就会将其整理出来。


推荐阅读