Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Text;
- using Newtonsoft.Json;
- using Newtonsoft.Json.Bson;
- namespace Ramp.Data
- {
- /// <summary>
- /// An interface to a key value store that provides support for JSON object serialization.
- /// </summary>
- public class JsonObjectStore
- {
- public const string IndexBucketName = "_JS_IDX";
- public const string VersionKey = "JS_Version";
- public const string BinaryKey = "JS_Binary";
- public const ushort Version = 1;
- private readonly IKeyValueStore _store;
- private readonly bool _binary;
- private readonly JsonSerializer _serializer;
- private readonly Encoding _encoding = new UTF8Encoding(false, true); // do not write utf8 byte mark
- /// <summary>
- /// Initialize the store.
- /// </summary>
- /// <param name="store"> The underlying key value store. </param>
- /// <param name="settings"> The JSON serializer settings. If null, uses default settings. </param>
- /// <param name="binary"> True to serialize using the binary BSON format. </param>
- public JsonObjectStore(IKeyValueStore store, JsonSerializerSettings settings = null, bool binary = false)
- {
- if (store == null)
- throw new ArgumentNullException("store");
- _store = store;
- _binary = binary;
- _serializer = settings == null ? JsonSerializer.CreateDefault() : JsonSerializer.Create(settings);
- Initialize();
- }
- /// <summary>
- /// Gets whether BSON is being used to store objects.
- /// </summary>
- public bool Binary
- {
- get { return _binary; }
- }
- /// <summary>
- /// Gets the underlying key value store.
- /// </summary>
- public IKeyValueStore Store
- {
- get { return _store; }
- }
- /// <summary>
- /// Get an object from the store.
- /// </summary>
- /// <typeparam name="T"> The object type. </typeparam>
- /// <param name="bucket"> The bucket. </param>
- /// <param name="key"> The key. </param>
- /// <param name="serializer"> The serializer to use for deserializing the object. If null, uses the default. </param>
- /// <returns> The deserialized object. </returns>
- public T GetObject<T>(string bucket, string key, JsonSerializer serializer = null)
- {
- serializer = serializer ?? _serializer;
- byte[] data = _store.GetBytesOrDefault(bucket, key);
- if (data == null)
- return default(T);
- using (JsonReader jreader = GetReader(data))
- {
- return serializer.Deserialize<T>(jreader);
- }
- }
- /// <summary>
- /// Set an object in the store.
- /// </summary>
- /// <typeparam name="T"> The object type. </typeparam>
- /// <param name="bucket"> The bucket. </param>
- /// <param name="key"> The key. </param>
- /// <param name="value"> The object. </param>
- /// <param name="serializer"> The serializer to use for serializing the object. If null, uses the default. </param>
- public void SetObject<T>(string bucket, string key, T value, JsonSerializer serializer = null)
- {
- serializer = serializer ?? _serializer;
- MemoryStream mstream;
- using (JsonWriter jwriter = GetWriter(out mstream))
- {
- serializer.Serialize(jwriter, value, typeof(T));
- jwriter.Flush();
- _store.Set(bucket, key, mstream.ToArray());
- }
- }
- /// <summary>
- /// Gets all objects in a bucket.
- /// </summary>
- /// <typeparam name="T"> The object type. </typeparam>
- /// <param name="bucket"> The bucket. </param>
- /// <param name="serializer"> The serializer to use for serializing the object. If null, uses the default. </param>
- /// <returns> An enumerable object providing all keys and objects in the specified bucket. </returns>
- public IEnumerable<KeyValuePair<string, T>> GetObjects<T>(string bucket, JsonSerializer serializer)
- {
- serializer = serializer ?? _serializer;
- foreach (KeyValuePair<string, byte[]> item in _store.GetItemBytes(bucket))
- {
- using (JsonReader jreader = GetReader(item.Value))
- {
- yield return new KeyValuePair<string, T>(item.Key, serializer.Deserialize<T>(jreader));
- }
- }
- }
- private void Initialize()
- {
- // Verison check
- var version = _store.GetValueOrDefault<int>(_store.MetadataBucketName, VersionKey);
- if (version > Version)
- throw new InvalidDataException("Store version is higher than current verison.");
- version = 1;
- _store.Set(_store.MetadataBucketName, VersionKey, version);
- // Format check
- bool currentlyBinary = _store.GetValueOrDefault<bool?>(_store.MetadataBucketName, BinaryKey) ?? _binary;
- if (currentlyBinary != _binary)
- throw new InvalidOperationException("Existing store has different format.");
- _store.Set(_store.MetadataBucketName, BinaryKey, _binary);
- }
- private JsonReader GetReader(byte[] data)
- {
- if (_binary)
- return new BsonReader(new BinaryReader(new MemoryStream(data, false), _encoding), false,
- DateTimeKind.Utc);
- return new JsonTextReader(new StreamReader(new MemoryStream(data, false), _encoding));
- }
- private JsonWriter GetWriter(out MemoryStream stream)
- {
- stream = new MemoryStream();
- if (_binary)
- return new BsonWriter(new BinaryWriter(stream, _encoding)) { DateTimeKindHandling = DateTimeKind.Utc };
- return new JsonTextWriter(new StreamWriter(stream, _encoding));
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment