Json.NET的自定义序列化器,仅适用于一个属性

41

更新:找到了问题 -- 继承错误的类,需要继承JsonConverter。

我有一个类,其中有一个类型为System.Data.Entity.Spatial.DbGeography的Location属性。默认的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()方法吗?

3个回答

59

你可以像这样为单个属性添加自定义序列化程序:

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 = (DateTime) value;
        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属性。


2
奖励:如果您需要疯狂的格式,例如将日期写为JavaScript“Date”对象,则可以使用writer.WriteRawValue - drzaus

9

结果是,我只需要从JsonConverter继承而不是CustomCreationConverter,并且我一直试图更改的其他所有内容都没问题。

我仍然不确定是否有一种流畅应用JsonConverter的方法,但是有另一种方式可以应用JsonConverter,而无需在您的领域/核心项目中引用Json.NET或标记您的领域类以引用外围库:

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

9

在属性上使用 JsonConverterAttribute 并定义一个自定义转换器。

例如,我们有一个属性作为 Unix 值(长整型)输入,我们将其序列化为 .Net 的 DateTime

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

4
你能提供更多关于如何将它们全部连起来的信息吗?我试了两次但没有效果。我会更新我的问题并提供更多信息。 - Kevin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接