public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if( reader.TokenType == JsonToken.Null ) { return null; } if( reader.TokenType != JsonToken.StartObject ) { var msg = string.Join(" ", $"The JSON representation of binary data (byte[]) when parsing the server response is not a {Converter.PseudoTypeKey}:{Converter.Binary} object.", $"This happens if your JSON document contains binary data (byte[]) in some other format (like a base64 string only) rather than a native RethinkDB pseudo type {Converter.PseudoTypeKey}:{Converter.Binary} object.", $"If you are overriding the default Ser/Deserialization process, you need to make sure byte[] is a native {Converter.PseudoTypeKey}:{Converter.Binary} objects before using the built-in {nameof(ReqlBinaryConverter)}.", "See https://rethinkdb.com/docs/data-types/ for more information about how binary data is represented in RethinkDB."); throw new JsonSerializationException(msg); } reader.ReadAndAssertProperty(Converter.PseudoTypeKey); var reql_type = reader.ReadAsString(); if( reql_type != Converter.Binary ) { throw new JsonSerializationException($"Expected {Converter.PseudoTypeKey} should be {Converter.Binary} but got {reql_type}."); } reader.ReadAndAssertProperty("data"); var data = reader.ReadAsBytes(); //realign and get out of the pseudo type //one more post read to align out of { reql_type:BINARY, data:""} reader.ReadAndAssert(); return data; }
//EXAMPLE: // "r": [ // { // "$reql_type$": "GROUPED_DATA", // "data": [ // [ // "Alice", // [ // { "id": 5, "player": "Alice", "points": 7, "type": "free"}, // { "id": 12, "player": "Alice", "points": 2, "type": "free" } // ] // ], // [ // "Bob", // [ // { "id": 2, "player": "Bob", "points": 15, "type": "ranked" }, // { "id": 11, "player": "Bob", "points": 10, "type": "free" } // ] // ] // ] // } // ] public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { reader.ReadAndAssertProperty(Converter.PseudoTypeKey); var reql_type = reader.ReadAsString(); if( reql_type != Converter.GroupedData ) { throw new JsonSerializationException($"Expected {Converter.PseudoTypeKey} should be {Converter.GroupedData} but got {reql_type}."); } reader.ReadAndAssertProperty("data"); //move reader to property value reader.ReadAndAssert(); //... probably find a better way to do this. var listType = typeof(List<>).MakeGenericType(objectType); var list = (IList)Activator.CreateInstance(listType); var data = serializer.Deserialize<List<JArray>>(reader); foreach( var group in data ) { var key = group[0]; //key, group value in common var items = group[1]; //the grouped items var grouping = Activator.CreateInstance(objectType, key, items); list.Add(grouping); } //.Select(arr => Activator.CreateInstance(objectType, arr) ).ToList(); return list; }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if( reader.TokenType != JsonToken.StartObject ) { var msg = string.Join(" ", $"The JSON representation of a DateTime/DateTimeOffset when parsing the server response is not a {Converter.PseudoTypeKey}:{Converter.Time} object.", $"This happens if your JSON document contains DateTime/DateTimeOffsets in some other format (like an ISO8601 string) rather than a native RethinkDB pseudo type {Converter.PseudoTypeKey}:{Converter.Time} object.", $"If you are overriding the default Ser/Deserialization process, you need to make sure DateTime/DateTimeOffset are native {Converter.PseudoTypeKey}:{Converter.Time} objects before using the built-in {nameof(ReqlDateTimeConverter)}.", "See https://rethinkdb.com/docs/data-types/ for more information about how Date and Times are represented in RethinkDB."); throw new JsonSerializationException(msg); } reader.ReadAndAssertProperty(Converter.PseudoTypeKey); var reql_type = reader.ReadAsString(); if( reql_type != Converter.Time ) { throw new JsonSerializationException($"Expected {Converter.PseudoTypeKey} should be {Converter.Time} but got {reql_type}."); } reader.ReadAndAssertProperty("epoch_time"); var epoch_time = reader.ReadAsDecimal(); if( epoch_time == null ) { throw new JsonSerializationException($"The {Converter.PseudoTypeKey}:{Converter.Time} object doesn't have an epoch_time value."); } reader.ReadAndAssertProperty("timezone"); var timezone = reader.ReadAsString(); //realign and get out of the pseudo type //one more post read to align out of { reql_type:TIME, .... } reader.ReadAndAssert(); var tz = TimeSpan.Parse(timezone.Substring(1)); if( !timezone.StartsWith("+") ) tz = -tz; var epoch = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero); var dt = epoch + TimeSpan.FromSeconds(Convert.ToDouble(epoch_time.Value)); var dto = dt.ToOffset(tz); if( objectType == typeof(DateTimeOffset) ) return dto; var tzHandle = serializer.DateTimeZoneHandling; switch( tzHandle ) { case DateTimeZoneHandling.Local: return dto.LocalDateTime; case DateTimeZoneHandling.Utc: return dto.UtcDateTime; case DateTimeZoneHandling.Unspecified: return dto.DateTime; case DateTimeZoneHandling.RoundtripKind: return dto.Offset == TimeSpan.Zero ? dto.UtcDateTime : dto.LocalDateTime; default: throw new JsonSerializationException("Invalid date time handling value."); } }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if( reader.TokenType == JsonToken.Null ) { return null; } if( reader.TokenType != JsonToken.StartObject ) { var msg = string.Join(" ", $"The JSON representation of a DateTime/DateTimeOffset when parsing the server response is not a {Converter.PseudoTypeKey}:{Converter.Time} object.", $"This happens if your JSON document contains DateTime/DateTimeOffsets in some other format (like an ISO8601 string) rather than a native RethinkDB pseudo type {Converter.PseudoTypeKey}:{Converter.Time} object.", $"If you are overriding the default Ser/Deserialization process, you need to make sure DateTime/DateTimeOffset are native {Converter.PseudoTypeKey}:{Converter.Time} objects before using the built-in {nameof(ReqlDateTimeConverter)}.", "See https://rethinkdb.com/docs/data-types/ for more information about how Date and Times are represented in RethinkDB."); throw new JsonSerializationException(msg); } reader.ReadAndAssertProperty(Converter.PseudoTypeKey); var reql_type = reader.ReadAsString(); if( reql_type != Converter.Time ) { throw new JsonSerializationException($"Expected {Converter.PseudoTypeKey} should be {Converter.Time} but got {reql_type}."); } reader.ReadAndAssertProperty("epoch_time"); var epoch_time = reader.ReadAsDouble(); if( epoch_time == null ) { throw new JsonSerializationException($"The {Converter.PseudoTypeKey}:{Converter.Time} object doesn't have an epoch_time value."); } reader.ReadAndAssertProperty("timezone"); var timezone = reader.ReadAsString(); //realign and get out of the pseudo type //one more post read to align out of { reql_type:TIME, .... } reader.ReadAndAssert(); if( objectType == typeof(DateTimeOffset) || objectType == typeof(DateTimeOffset?) ) { return ConvertDateTimeOffset(epoch_time.Value, timezone); } else { return ConvertDateTime(epoch_time.Value, timezone, serializer.DateTimeZoneHandling); } }