Подтвердить что ты не робот

Запустить логику сериализации по умолчанию от JsonConverter

У меня есть JsonConverter, который, в зависимости от флага конкретного экземпляра, должен либо

  • запустить пользовательскую логику сериализации
  • запустить стандартную логику сериализации Json.NET

Как можно запускать логику сериализации по умолчанию Json.NET с JsonConverter?

Спасибо

4b9b3361

Ответ 1

Вот пример. Скажем, ваш класс для сериализации выглядит следующим образом:

class Foo
{
    public bool IsSpecial { get; set; }
    public string A { get; set; }
    public string B { get; set; }
    public string C { get; set; }
}

Флаг IsSpecial используется для контроля того, делаем ли мы что-то особенное в конвертере или просто позволяем вещам естественно сериализоваться. Вы можете написать свой конвертер следующим образом:

class FooConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(Foo).IsAssignableFrom(objectType);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        Foo foo = (Foo)value;
        JObject jo;
        if (foo.IsSpecial)
        {
            // special serialization logic based on instance-specific flag
            jo = new JObject();
            jo.Add("names", string.Join(", ", new string[] { foo.A, foo.B, foo.C }));
        }
        else
        {
            // normal serialization
            jo = JObject.FromObject(foo);
        }
        jo.WriteTo(writer);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

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

class Program
{
    static void Main(string[] args)
    {
        List<Foo> foos = new List<Foo>
        {
            new Foo
            {
                A = "Moe",
                B = "Larry",
                C = "Curly",
                IsSpecial = false
            },
            new Foo
            {
                A = "Huey",
                B = "Dewey",
                C = "Louie",
                IsSpecial = true
            },
        };

        JsonSerializerSettings settings = new JsonSerializerSettings();
        settings.Converters.Add(new FooConverter());
        settings.Formatting = Formatting.Indented;

        string json = JsonConvert.SerializeObject(foos, settings);
        Console.WriteLine(json);
    }
}

Вывод:

[
  {
    "IsSpecial": false,
    "A": "Moe",
    "B": "Larry",
    "C": "Curly"
  },
  {
    "names": "Huey, Dewey, Louie"
  }
]

Ответ 2

Вы можете изменить свойство CanWrite, чтобы отключить собственный сериализатор. Это не будет работать правильно, если объект может содержать дочерние объекты того же типа.

class FooConverter : JsonConverter
{
    bool _canWrite = true;
    public override bool CanWrite
    {
        get { return _canWrite;}
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        Foo foo = (Foo)value;
        JObject jo;
        if (foo.IsSpecial)
        {
            // special serialization logic based on instance-specific flag
            jo = new JObject();
            jo.Add("names", string.Join(", ", new string[] { foo.A, foo.B, foo.C }));
        }
        else
        {
            // normal serialization
            _canWrite = false;
            jo = JObject.FromObject(foo);
            _canWrite = true;
        }
        jo.WriteTo(writer);
    }
}