Json.net LinearGradientBrush сериализация

Я пытался сериализовать LinearGradientBrush (System.Windows.Media.LinearGradientBrush) с Json.net, но безуспешно:

var lg = new LinearGradientBrush();
lg.StartPoint = new Point(2,3);
lg.EndPoint = new Point(3.1,0);
lg.GradientStops = new GradientStopCollection(new []{ new GradientStop(Colors.Red, 0),new GradientStop(Colors.White, 1)});

var json = JsonConvert.SerializeObject(lg);

Этот код выведет строку, содержащую "System.Windows.Media.LinearGradientBrush" это явно неправильно.

Я попытался с сериализацией XML, и она работает как ожидалось:

var sb = new StringBuilder();
var writer = XmlWriter.Create(sb, new XmlWriterSettings(){ Indent=true});
var ser = new XmlSerializer(lg.GetType(), new []{ typeof(System.Windows.Media.MatrixTransform)});
ser.Serialize(writer,lg);
var xml = sb.ToString();

Почему сериализатору json не удается сериализовать LinearGradientBrush?

2 ответа

Библиотека Json.NET возникают некоторые проблемы при попытке сериализации сложных объектов, таких как массив, объект LinearGradientBrush или объект с расширенной структурой, например, словарь или что-то подобное (в случае LinearGradientBrush, существует структура данных GradientStopCollection, которая может быть причиной вашей проблемы).

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

Если это не помогает, возможно, это тот случай, когда нужно создать собственный конвертер для вашего объекта, как предлагается здесь, и использовать его при вызове метода SerializeObject() для сериализации вашего объекта.

Старый вопрос, но все еще актуальный с последним Json.NET.

Вы можете выбрать только сериализацию кисти как XAML. Это означает, что в результате вы получите XAML в своем файле JSON, но это самое чистое решение, которое я смог найти.

Над кистью используйте аннотацию JsonConvert:

[JsonConverter(typeof(BrushJsonConverter))]
public Brush Brush {get; set;}

И реализовать следующий JsonConverter:

/// <summary>
///     Stores a brush as XAML because Json.net has trouble saving it as JSON
/// </summary>
public class BrushJsonConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var jo = new JObject {{"value", XamlWriter.Save(value)}};
        jo.WriteTo(writer);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
        JsonSerializer serializer)
    {
        // Load JObject from stream
        var jObject = JObject.Load(reader);
        return XamlReader.Parse(jObject["value"].ToString());
    }

    public override bool CanConvert(Type objectType)
    {
        return typeof(Brush).IsAssignableFrom(objectType);
    }
}

РЕДАКТИРОВАТЬ: Если вы предпочитаете иметь чистый JSON, вы также можете сериализовать XAML в JSON. Это может ухудшить производительность, но это приведет к более аккуратному результату

/// <summary>
///     Stores a brush by temporarily serializing it to XAML because Json.NET has trouble 
///     saving it as JSON
/// </summary>
public class BrushJsonConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        // Turn the brush into an XML node
        var doc = new XmlDocument();
        doc.LoadXml(XamlWriter.Save(value));

        // Serialize the XML node as JSON
        var jo = JObject.Parse(JsonConvert.SerializeXmlNode(doc.DocumentElement));
        jo.WriteTo(writer);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
        JsonSerializer serializer)
    {
        // Load JObject from stream
        var jObject = JObject.Load(reader);

        // Seriaze the JSON node to XML
        var xml = JsonConvert.DeserializeXmlNode(jObject.ToString());
        return XamlReader.Parse(xml.InnerXml);
    }

    public override bool CanConvert(Type objectType)
    {
        return typeof(Brush).IsAssignableFrom(objectType);
    }
}
Другие вопросы по тегам