using System; using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using RethinkDb.Driver.Net.JsonConverters; using RethinkDb.Driver.Utils; namespace RethinkDb.Driver.Net { /// /// Configuration for RethinkDB's JSON serializer /// public static class Converter { static Converter() { InitializeDefault(); } /// /// Initializes default serializer settings. There is no need to call this manually /// as it is already initialized in the static constructor. /// public static void InitializeDefault() { Converters = new JsonConverter[] { DateTimeConverter = new ReqlDateTimeConverter(), BinaryConverter = new ReqlBinaryConverter(), GroupingConverter = new ReqlGroupingConverter(), PocoExprConverter = new PocoExprConverter(), }; var settings = new JsonSerializerSettings() { Converters = Converters }; Serializer = JsonSerializer.CreateDefault(settings); } /// /// An array of the JSON converters in this static class. /// public static JsonConverter[] Converters { get; set; } /// /// The JSON serializer used for ser/deser. /// public static JsonSerializer Serializer { get; set; } /// /// DateTime converter to/from ReQL pseudo types /// public static ReqlDateTimeConverter DateTimeConverter { get; set; } /// /// Binary converter to/from ReQL pseudo types /// public static ReqlBinaryConverter BinaryConverter { get; set; } /// /// DateTime converter from ReQL grouping types /// public static ReqlGroupingConverter GroupingConverter { get; set; } /// /// Allows anonymous types to be composed with ReQL expressions like R.Now() /// public static PocoExprConverter PocoExprConverter { get; set; } /// /// The pseudo type key /// public const string PseudoTypeKey = "$reql_type$"; /// /// Discriminator for TIME types. /// public const string Time = "TIME"; /// /// Discriminator for GROUPED_DATA types. /// public const string GroupedData = "GROUPED_DATA"; /// /// Discriminator for GEOMETRY types. /// public const string Geometry = "GEOMETRY"; /// /// Discriminator for BINARY types. /// public const string Binary = "BINARY"; /// /// Method for converting pseudo types in JToken (JObjects) /// public static void ConvertPseudoTypes(JToken data, FormatOptions fmt) { var reqlTypes = data.SelectTokens("$..$reql_type$").ToList(); foreach (var typeToken in reqlTypes) { var reqlType = typeToken.Value(); //JObject -> JProerty -> JVaule:$reql_type$, go backup the chain. var pesudoObject = typeToken.Parent.Parent as JObject; JToken convertedValue = null; if (reqlType == Time) { if (fmt.RawTime) continue; convertedValue = new JValue(GetTime(pesudoObject)); } else if (reqlType == GroupedData) { if (fmt.RawGroups) continue; convertedValue = GetGrouped(pesudoObject); } else if (reqlType == Binary) { if (fmt.RawBinary) continue; convertedValue = new JValue(GetBinary(pesudoObject)); } else if (reqlType == Geometry) { // Nothing specific here continue; } else { // Just leave unknown pseudo-types alone continue; } pesudoObject.Replace(convertedValue); } } private static object GetTime(JObject value) { double epoch_time = value["epoch_time"].ToObject(); string timezone = value["timezone"].ToString(); if (Serializer.DateParseHandling == DateParseHandling.DateTime) { return ReqlDateTimeConverter.ConvertDateTime(epoch_time, timezone, Serializer.DateTimeZoneHandling); } else { return ReqlDateTimeConverter.ConvertDateTimeOffset(epoch_time, timezone); } } private static byte[] GetBinary(JObject value) { var base64 = value["data"].Value(); return Convert.FromBase64String(base64); } private static JToken GetGrouped(JObject value) { return value["data"]; } } }