【问题标题】:Different JsonSerializerSettings for different values in list [duplicate]列表中不同值的不同 JsonSerializerSettings [重复]
【发布时间】:2020-07-11 08:41:04
【问题描述】:

我正在使用此设置来序列化 dotnet core 2.2 中的对象列表:

var settings = new JsonSerializerSettings()
{
    DateFormatString = "MM/dd/yyyy h:mm tt"
}

问题是,如果 DateTimes 时间等于 0,我希望它使用“MM/dd/yyyy”序列化和反序列化 DateTimes,并且我发现没有动态方法可以在具有两个值的同一列表中执行此操作(DateTimes 具有不同的时间, 0 或不 0)

【问题讨论】:

  • 创建您自己的JsonConverter。并且没有理由停留在 2.2 而不迁移到 3.1。
  • 我打算继承JsonConvertor。这个问题的目的是使用任何潜在的现有特性,它优于继承。但似乎派生类是唯一的方法。关于 dotnet 2.2:我们正在考虑直接迁移到 dotnet 5。但我不是决定时间的人。
  • .NET 5(稳定版)在未来还很遥远,对我来说这不是一个好主意。对我来说,最好继续 3.1(它是 LTS,稳定,现在和现在),然后转到 .NET 6,因为 .NET 5 是过渡版本,不会包含所有需要的功能。 2.2 is outdated,并且可能容易受到攻击。顺便说一句,是的,JsonConverter 是实现自定义解散行为的唯一方法。
  • 也是.NET 6 will be LTS,不是.NET 5
  • 正确,感谢您的建议。仍然让我们坚持问题的重点。请问一招,缓解这个问题的解决办法吗?

标签: c# .net json.net .net-core-2.2


【解决方案1】:

您可以为此编写自己的 json 转换器。

public class DateTimeStringConverter : JsonConverter
{
    // allowable DateTime formats - update as required
    List<string> DateFormats => new List<string> { "MM/dd/yyyy", "MM/dd/yyyy h:mm tt" };

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var dateStr = (string)reader.Value;
        DateTime date;
        foreach (string format in DateFormats)
        {
            if (DateTime.TryParseExact(dateStr, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out date))
            {
                return date;
            }
        }

        throw new JsonException($"{dateStr} as not a valid date string.");
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        DateTime date = DateTime.Parse(value.ToString());
        // Time value of DateTime.Today is always "00:00:00"
        if (date.TimeOfDay == DateTime.Today.TimeOfDay)
        {
            serializer.Serialize(writer, date.ToString("MM/dd/yyyy"));
        }
        else
        {
            serializer.Serialize(writer, date.ToString("MM/dd/yyyy h:mm tt"));
        }
    }

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

您可以通过将DateFormats 更改为公共列表并在初始化JsonSerializerSettings 时传递有效的日期时间格式来改进这一点。

然后你可以应用这样的设置:

var settings = new JsonSerializerSettings();
settings.DateParseHandling = DateParseHandling.None;
settings.Converters.Add(new DateTimeStringConverter());

// deserialize
var model = JsonConvert.DeserializeObject<YourClass>(json, settings);

// serialize
var serializedJson = JsonConvert.SerializeObject(model, settings);

这是受到question的答案的启发

【讨论】:

  • 这将涵盖我的部分要求。但是我的一些对象是匿名的,或者是 类型的字典。我有什么可以为他们做的吗?它们是序列化中最重要的部分。
  • 您的链接为我指出了真正的解决方案。我会更新对我有用的东西。谢谢
  • @FarhadGh 我已经更新了我的答案以更好地满足您的要求,并且还实施了序列化(昨天没时间更新答案)。
猜你喜欢
  • 1970-01-01
  • 2022-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-19
  • 2021-09-03
  • 1970-01-01
相关资源
最近更新 更多