Run default serialization logic from JsonConverter

て烟熏妆下的殇ゞ 提交于 2019-12-20 10:18:35

问题


I have a JsonConverter that, depending on an instance specific flag, needs to either

  • run custom serialization logic
  • run the default Json.NET serialization logic

How can the default Json.NET serialization logic be ran from a JsonConverter?

Thanks


回答1:


Here is an example. Say your class to serialize looks like this:

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

The IsSpecial flag is used to control whether we do something special in the converter or just let things serialize naturally. You can write your converter like this:

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

Then, to use the converter, pass an instance of it to the SerializeObject method (e.g. in the settings). (Do NOT decorate the target class with a JsonConverter attribute, or this will result in an infinite recursive loop when you serialize.)

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

Output:

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



回答2:


You can change the CanWrite property to disable a custom serializer. This won't work right if the object can contain children of the same type or if you are serializing in more than one thread.

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


来源:https://stackoverflow.com/questions/21366328/run-default-serialization-logic-from-jsonconverter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!