Пользовательский сериализатор только для одного свойства в Json.NET

ОБНОВЛЕНИЕ Обнаружил проблему - наследовал от неправильного класса, должен быть JsonConverter.

У меня есть класс, который имеет свойство Location типа System.Data.Entity.Spatial.DbGeography. Сериализатор Json.NET по умолчанию выводит текст JSON следующим образом:

  ...
  "PlaceType": 0,
  "Location": {
    "Geography": {
      "CoordinateSystemId": 4326,
      "WellKnownText": "POINT (-88.00000 44.00000)"
    }
  },
  "AddedDT": null,
  ...

Я хочу, чтобы это выглядело так:

  ...
  "PlaceType": 0,
  "Location": [-88.00000,44.00000],
  "AddedDT": null,
  ...

... так что мне кажется, что я должен сделать, это переопределить любой конвертер, используемый в настоящее время для типа DbGeography.

Примеры, которые я до сих пор видел, которые используют CustomCreationConverters и ContractResolvers, похоже, касаются того, как вы замените сериализатор для сериализуемого основного класса, а не для типа, который является только свойством этого класса. Примеры, которые включают аннотирование класса, который переопределяется, не работают для меня, потому что я не определяю DbGeography в своем коде, и это фактически закрытый класс, потому что он не имеет конструктора и может быть создан только internal методами фабрики.

Есть ли способ применить JsonConverter к типу свободно? Если так, то как бы выглядел конвертер? Должен ли я просто переопределить метод WriteJson()?

Ответ 1

Оказывается, мне просто нужно было наследовать от JsonConverter вместо CustomCreationConverter, и все остальное, что я пытался изменить, было хорошо все время.

Я все еще не уверен, есть ли способ применить JsonConverter плавно, но есть другой способ применения JsonConverter без ссылки на Json.NET в вашем доменном/базовом проекте или маркировки ваших классов домена ссылками на периферийные устройства библиотека:

var jsonSerializer = new JsonSerializer();
jsonSerializer.Converters.Add(new DbGeographyConverter());
jsonSerializer.Serialize(jsonWriter, place);

Ответ 2

Вы можете добавить собственный сериализатор к одному атрибуту, например так:

public class Comment
{
    public string Author { get; set; }

    [JsonConverter(typeof(NiceDateConverter))]
    public DateTime Date { get; set; }

    public string Text { get; set; }
}

public class NiceDateConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var date = value as DateTime;
        var niceLookingDate = date.ToString("MMMM dd, yyyy 'at' H:mm tt");
        writer.WriteValue(niceLookingDate);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException("Unnecessary because CanRead is false. The type will skip the converter.");
    }

    public override bool CanRead
    {
        get { return false; }
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(DateTime);
    }
}

Затем, когда вы сериализуете свой объект с помощью JsonConvert.SerializeObject(), для свойства Date будет использоваться пользовательский сериализатор.

Ответ 3

Используйте JsonConverterAttribute для свойства и определите пользовательский converter-

например, у нас есть свойство, которое входит в значение unix (long int), и мы сериализуем его в .Net DateTime:

[JsonConverter(typeof(UnixTimeJsonConverter))]
public DateTime Requested { get; set; }