Сериализация null в JSON.NET

При сериализации произвольных данных через JSON.NET любое свойство, которое является null, записывается в JSON как

"propertyName" : null

Это, конечно, правильно.

Однако у меня есть требование автоматически преобразовывать все нули в пустое значение по умолчанию, например, null strings должен стать String.Empty, null int?s должен стать 0, null bool?s должен стать false, и так далее.

NullValueHandling не помогает, поскольку я не хочу игнорировать нули, но и не хочу включать их (Хм, новая функция?).

Поэтому я обратился к реализации пользовательского JsonConverter.
Хотя сама реализация была легкой, к сожалению, это все равно не сработало - CanConvert() никогда не вызывается для свойства с нулевым значением, и поэтому WriteJson() тоже не вызывается. По-видимому, нули автоматически сериализуются непосредственно в null, без специального конвейера.

Например, вот пример пользовательского конвертера для нулевых строк:

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

    ...
    public override void WriteJson(JsonWriter writer, 
                object value, 
                JsonSerializer serializer)
    {
        string strValue = value as string;

        if (strValue == null)
        {
            writer.WriteValue(String.Empty);
        }
        else
        {
            writer.WriteValue(strValue);
        }
    }
}

Пройдя через это в отладчике, я заметил, что ни один из этих методов не вызывается для свойств, имеющих нулевое значение.

Заглянув в исходный код JSON.NET, я обнаружил, что (видимо, я не очень глубоко вникал) существует специальный случай, проверяющий нули и явно вызывающий .WriteNull().

Если уж на то пошло, я попробовал реализовать собственный JsonTextWriter и переопределить стандартную реализацию .WriteNull()...

public class NullJsonWriter : JsonTextWriter
{
    ... 
    public override void WriteNull()
    {
        this.WriteValue(String.Empty);
    }
}

Однако это не может работать хорошо, поскольку метод WriteNull() ничего не знает о базовом типе данных. Так что, конечно, я могу вывести """ для любого null, но это не работает для, например, int, bool и т.д.

Итак, мой вопрос - если не преобразовывать всю структуру данных вручную, есть ли какое-нибудь решение или обходной путь для этого?

46
задан AviD 21 August 2012 в 07:11
поделиться