将Firestore Timestamp转换为JSON(Newtonsoft)返回空对象

dwthyt8l  于 2023-05-02  发布在  其他
关注(0)|答案(1)|浏览(150)

我正在从Firestore数据库阅读数据,并使用C# Web API中的Newtonsoft将其转换为JSON。但是,时间戳字段始终转换为空对象。

ds is a DocumentSnapshot
  Dictionary<string, object> d = ds.ToDictionary();
  JToken jt = JToken.FromObject(d);

上面的代码返回了一个空的“date”字段对象,它是一个Firestore Timestamp:

date: {}

我做了以下工作作为变通:

var dt  = d.GetValueOrDefault("date");
  if (dt != null)
  {
    var dts = dt.ToString().Remove(0, 11);
    d["date"] = dts;
  }

我已经尝试了各种日期选项的转换,但没有一个做任何事情。

lnlaulya

lnlaulya1#

类型Google.Cloud.Firestore.Timestamp没有公共属性,这就是它被序列化为空对象{}的原因。要将其序列化为RFC 3339 UTC Timestamp字符串,您需要创建一个custom JsonConverter<Timestamp>

public class TimestampConverter : JsonConverter<Google.Cloud.Firestore.Timestamp> // namespace added for clarity
{
    //https://cloud.google.com/dotnet/docs/reference/Google.Cloud.Firestore/latest/Google.Cloud.Firestore.Timestamp
    public override Timestamp ReadJson(JsonReader reader, Type objectType, Timestamp existingValue, bool hasExistingValue, JsonSerializer serializer) =>
        Timestamp.FromDateTime(serializer.Deserialize<DateTime>(reader).ToUniversalTime());

    public override void WriteJson(JsonWriter writer, Timestamp value, JsonSerializer serializer) =>
        writer.WriteRawValue(JsonConvert.ToString(value.ToDateTime(), DateFormatHandling.IsoDateFormat, DateTimeZoneHandling.Utc));
}

或者,如果您需要生成的JSON Timestamp值精确地遵守Google预期的RFC 3339格式,您可以使用Google.Apis.Json.RFC3339DateTimeConverter来格式化值:

public class TimestampConverter : JsonConverter<Google.Cloud.Firestore.Timestamp> // namespace added for clarity
{
    //https://cloud.google.com/dotnet/docs/reference/Google.Apis/latest/Google.Apis.Json.RFC3339DateTimeConverter
    //A JSON converter which honers RFC 3339 and the serialized date is accepted by Google services.
    static readonly Google.Apis.Json.RFC3339DateTimeConverter googleDateTimeConverter = new();
    
    //https://cloud.google.com/dotnet/docs/reference/Google.Cloud.Firestore/latest/Google.Cloud.Firestore.Timestamp
    public override Timestamp ReadJson(JsonReader reader, Type objectType, Timestamp existingValue, bool hasExistingValue, JsonSerializer serializer) =>
        Timestamp.FromDateTime(serializer.Deserialize<DateTime>(reader).ToUniversalTime());

    public override void WriteJson(JsonWriter writer, Timestamp value, JsonSerializer serializer) =>
        googleDateTimeConverter.WriteJson(writer, value.ToDateTime(), serializer);
}

无论哪种方式,都要使用以下设置序列化为JToken

var settings = new JsonSerializerSettings
{
    Converters = { new TimestampConverter() },
};
var jt = JToken.FromObject(d, JsonSerializer.Create(settings));

或者转换为JSON字符串,如下所示:

var json = JsonConvert.SerializeObject(d, settings);

字典d的JSON结果如下所示:

{"date":"2023-04-11T21:01:01.110101Z"}

对于第一个转换器,或

{"date":"2023-04-11T21:08:01.110Z"}

第二个(区别似乎只是在精度上。)
演示小提琴herehere

相关问题