【问题标题】:How to format date in LINQ without explicity listing every column?如何在 LINQ 中格式化日期而不明确列出每一列?
【发布时间】:2013-06-11 20:35:02
【问题描述】:

我收到 JSON 字符串中的日期错误:/Date(1370963229000)/ is not a valid value for DateTime.,我可以通过在日期上执行 ToString("g") 来解决此问题,但我不想必须明确地将每一列都放在我的选择语句。

目前,我正在做:

var people = _context.People.ToList();

我不想做var people = _context.People.Select({x=>x.Id.....});

【问题讨论】:

  • 选择有什么问题?
  • @newStackExchangeInstance - 一个表中可能有 200 列,我不想为了修改日期而列出所有 200 列。如果我不必这样做,我对 Select 没有任何问题。我必须返回所有列,但我只需要修改日期。
  • 你到底在哪里得到错误?当您尝试使用来自people 列表的数据时,或者当它从 JSON 中填充时?您能否详细说明从何处获取数据?
  • @Floremin - 当我尝试使用 Date 反序列化 JSON 字符串时,实际上会发生错误。
  • 但是,您必须在拥有_context.People 之前的日期执行ToString("g") 吗?我不明白你正在使用的过程以及它在哪里中断。

标签: c# json linq


【解决方案1】:

方法一:使用“代理”属性

[ScriptIgnore] 属性放在DateTime 属性上,并实现将日期值作为字符串获取的代理属性。带有[ScriptIgnore] 的属性将被JavaScriptSerializer 跳过,并且将发出代理属性。例如:

[ScriptIgnore]
public DateTime DateValue { get; set; }

public string DateValueJS
{
    get { return DateValue.ToString("g"); }
}

方法 2:使用带有 JavaScriptSerializer 的 CustomConverters

使用 JavaScriptSerializer 中内置的 CustomConverters 支持来注册您自己的类以处理特定类型的序列化。例如:

public class DateJsonConverter : JavaScriptConverter
{
    public override IEnumerable<Type> SupportedTypes
    {
        get { return new Type[] { typeof(DateTime) }; }
    }

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {            
        return new Dictionary<string, object>()
        {
            { "Value", ((DateTime)obj).ToString("g") }
        };
    }

    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
    {
        throw new NotSupportedException();
    }
}

你可以像这样使用这个自定义转换器:

var serializer = new JavaScriptSerializer();

serializer.RegisterConverters(new JavaScriptConverter[] { new DateJsonConverter() });

该类将日期值序列化为:{"Dt":{"Value":"6/11/2013 5:36 PM"}}

方法3:使用Reflection透明格式化DateTime

当值被序列化时,您可以使用反射将DateTime 值透明地转换为string 值。例如:

private static object FormatDateTime(object x)
{
    if (x == null || x is IEnumerable)
        return x;

    var t = x.GetType();

    if (t == typeof(DateTime))
        return ((DateTime)x).ToString("g");

    if (t.IsPrimitive)
        return x;

    var result = new Dictionary<string, object>();

    foreach (var prop in t.GetProperties())
    {
        // Skip properties with ScriptIgnoreAttribute
        if (prop.GetCustomAttributes(typeof(ScriptIgnoreAttribute), true).Any())
            continue;

        result[prop.Name] = FormatDateTime(prop.GetValue(x, null));
    }

    return result;
}

此方法可在您的 Select 语句中使用,以将对象值转换为 DictionaryJavaScriptSerializer 可以使用该 JavaScriptSerializer 来发出 JSON。例如:

var value = new[] { new { Dt = DateTime.Now, Childs = new[] { 1, 2, 3 } } };
serializer.Serialize(value.Select(x => FormatDateTime(x)))

将发出[{"Dt":"6/12/2013 3:27 PM","Childs":[1,2,3]}]

【讨论】:

  • @Xaisoft,您需要日期值是字符串,而不是子对象?
  • @Xaisoft,我添加了其他建议
  • 感谢您的建议,我最终只是从实体中明确选择了字段并在那里格式化了日期。这也让我不用在 Json 字符串中返回 EntityState、EntityKey,所以无论如何这是我必须做的。
【解决方案2】:

我从未使用过JavaScriptSerializer,但如果您对数据的反序列化方式有任何影响,我建议将此数据字段反序列化为字符串,然后在Person 类上设置一个属性,该属性将返回值转换为DateTime

【讨论】:

    猜你喜欢
    • 2016-12-07
    • 2016-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-22
    相关资源
    最近更新 更多