【问题标题】:JArray silently ignoring members [closed]JArray默默地忽略成员[关闭]
【发布时间】:2022-02-11 22:14:58
【问题描述】:

我正在尝试反序列化 JSON 的 sn-p,看起来像这样:

{
    "timePoints": [ "2020", "2020-1-9", "2020-4-1" ]
}

这里的想法是,我们将允许一个完全限定的日期,或者只允许一个将转换为名义日期的年份。所以我创建了一个自定义的 JsonConverter 来处理这个字段:

public class Foo
{
    [JsonConverter(typeof(TimePointConverter))]
    public IEnumerable<DateTime> TimePoints { get; set; }
}

public class TimePointConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        reader.DateParseHandling = DateParseHandling.None;

        var obj = JArray.ReadFrom(reader);
        var points = obj.Select(x =>
        {
            if (!DateTime.TryParse(x.ToString(), out var date))
            {
                if (int.TryParse(x.ToString(), out int year) && year > 0)
                {
                    date = new DateTime(year, 10, 1);   // qtr 4
                }
                else
                {
                    throw new FormatException($"Unable to parse date: {x.ToString()} is invalid.");
                }
            }
            return date;
        });
        return points.Any() ? points.ToArray() : null;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

但问题是JArray.ReadFrom 会自动尝试将2020-1-92020-4-1 解释为日期。但由于2020 不是日期,它完全忽略了它。所以我最终得到obj 是两个日期的数组,默默地忽略第三项。我该如何阻止这种行为?我希望它把这些读成字符串,而不是日期? DateParseHandling.None 好像完全没有效果。

更新:原来我找错地方了。在它到达我正在查看的应用程序之前,它已经在其他地方被序列化,并且正在删除非日期项目。现在结束这个问题...

【问题讨论】:

标签: c# json.net


【解决方案1】:

这对我有用

Foo.cs

public sealed record Foo(IReadOnlyCollection<DateTime> TimePoints);

主要方法

    var json = @"
{
    ""timePoints"": [ ""2020"", ""2020-1-9"", ""2020-4-1"" ]
}";

    var settings = new JsonSerializerSettings
    {
        Converters = new List<JsonConverter> { new TimePointConverter() }
    };

    var foo = JsonConvert.DeserializeObject<Foo>(json, settings);

转换器

public class TimePointConverter : JsonConverter
{
    public override object? ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        reader.DateParseHandling = DateParseHandling.None;

        var obj = JArray.ReadFrom(reader);
        // select 'timePoints' element from the json
        var points = obj["timePoints"]?.Select(x =>
        {
            if (!DateTime.TryParse(x.ToString(), out var date))
            {
                if (int.TryParse(x.ToString(), out int year) && year > 0)
                {
                    date = new DateTime(year, 10, 1);   // qtr 4
                }
                else
                {
                    throw new FormatException($"Unable to parse date: {x.ToString()} is invalid.");
                }
            }
            return date;
        });
        
        // returns a Foo rather than list of DateTimes
        return points is not null && points.Any() 
            ? new Foo(points.ToArray())
            : null;
    }

    public override bool CanConvert(Type objectType) 
        => true;

    public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) 
        => throw new NotImplementedException();
}

但我假设你打电话给DeserializeObject&lt;Foo&gt;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-26
    • 2014-01-03
    • 1970-01-01
    • 1970-01-01
    • 2011-11-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多