public static LdValue ReadJsonValue(ref JReader reader) { var value = reader.Any(); switch (value.Type) { case JsonStream.ValueType.Bool: return(LdValue.Of(value.BoolValue)); case JsonStream.ValueType.Number: return(LdValue.Of(value.NumberValue)); case JsonStream.ValueType.String: return(LdValue.Of(value.StringValue.ToString())); case JsonStream.ValueType.Array: var arrayBuilder = LdValue.BuildArray(); for (var arr = value.ArrayValue; arr.Next(ref reader);) { arrayBuilder.Add(ReadJsonValue(ref reader)); } return(arrayBuilder.Build()); case JsonStream.ValueType.Object: var objBuilder = LdValue.BuildObject(); for (var obj = value.ObjectValue; obj.Next(ref reader);) { objBuilder.Add(obj.Name.ToString(), ReadJsonValue(ref reader)); } return(objBuilder.Build()); default: return(LdValue.Null); } }
internal static SegmentRule ReadSegmentRule(ref JReader reader) { ImmutableList <Clause> clauses = null; int? weight = null; UserAttribute?bucketBy = null; for (var obj = reader.Object(); obj.Next(ref reader);) { switch (obj.Name) { case var n when n == "clauses": clauses = SerializationHelpers.ReadClauses(ref reader); break; case var n when n == "weight": weight = reader.IntOrNull(); break; case var n when n == "bucketBy": var s = reader.StringOrNull(); bucketBy = s is null ? (UserAttribute?)null : UserAttribute.ForName(s); break; } } return(new SegmentRule(clauses, weight, bucketBy)); }
internal static PutData ParsePutData(byte[] json) { var r = JReader.FromUtf8Bytes(json); try { string path = null; FullDataSet <ItemDescriptor> data = new FullDataSet <ItemDescriptor>(); for (var obj = r.Object().WithRequiredProperties(_putRequiredProperties); obj.Next(ref r);) { if (obj.Name == "path") { path = r.String(); } else if (obj.Name == "data") { data = ParseFullDataset(ref r); } } return(new PutData(path, data)); } catch (Exception e) { throw r.TranslateException(e); } }
public FullDataSet <ItemDescriptor> Parse(string content, int version) { if (_alternateParser == null) { return(ParseJson(content, version)); } else { if (content.Trim().StartsWith("{")) { try { return(ParseJson(content, version)); } catch (Exception) { // we failed to parse it as JSON, so we'll just see if the alternate parser can do it } } // The alternate parser should produce the most basic .NET data structure that can represent // the file content, using types like Dictionary and String. We then convert this into a // JSON tree so we can use the JSON deserializer; this is inefficient, but it lets us reuse // our existing data model deserialization logic. var o = _alternateParser(content); var r = JReader.FromAdapter(ReaderAdapters.FromSimpleTypes(o, allowTypeCoercion: true)); return(ParseJson(ref r, version)); } }
internal static DeleteData ParseDeleteData(byte[] json) { var r = JReader.FromUtf8Bytes(json); try { DataKind kind = null; string key = null; int version = 0; for (var obj = r.Object().WithRequiredProperties(_deleteRequiredProperties); obj.Next(ref r);) { if (obj.Name == "path") { TryParsePath(r.String(), out kind, out key); } else if (obj.Name == "version") { version = r.Int(); } } return(new DeleteData(kind, key, version)); } catch (Exception e) { throw r.TranslateException(e); } }
internal static FullDataSet <ItemDescriptor> ParseFullDataset(ref JReader r) { try { var dataBuilder = ImmutableList.CreateBuilder <KeyValuePair <DataKind, KeyedItems <ItemDescriptor> > >(); for (var topLevelObj = r.Object(); topLevelObj.Next(ref r);) { var name = topLevelObj.Name.ToString(); var kind = DataModel.AllDataKinds.FirstOrDefault(k => name == PathNameForKind(k)); if (kind == null) { continue; } var itemsBuilder = ImmutableList.CreateBuilder <KeyValuePair <string, ItemDescriptor> >(); for (var itemsObj = r.Object(); itemsObj.Next(ref r);) { var key = itemsObj.Name.ToString(); var item = kind.DeserializeFromJReader(ref r); itemsBuilder.Add(new KeyValuePair <string, ItemDescriptor>(key, item)); } dataBuilder.Add(new KeyValuePair <DataKind, KeyedItems <ItemDescriptor> >(kind, new KeyedItems <ItemDescriptor>(itemsBuilder.ToImmutable()))); } return(new FullDataSet <ItemDescriptor>(dataBuilder.ToImmutable())); } catch (Exception e) { throw r.TranslateException(e); } }
internal DataKind( string name, SerializerToJWriter internalSerializer, DeserializerFromJReader internalDeserializer) { _name = name; _internalSerializer = internalSerializer; _internalDeserializer = internalDeserializer; _serializer = item => { var w = JWriter.New(); if (item.Item is null) { var obj = w.Object(); obj.Name("version").Int(item.Version); obj.Name("deleted").Bool(true); obj.End(); } else { internalSerializer(item.Item, w); } return(w.GetString()); }; _deserializer = s => { var r = JReader.FromString(s); return(_internalDeserializer(ref r)); }; }
private static ItemDescriptor DeserializeFlag(ref JReader r) { var flag = FeatureFlagSerialization.Instance.ReadJson(ref r) as FeatureFlag; return(flag.Deleted ? ItemDescriptor.Deleted(flag.Version) : new ItemDescriptor(flag.Version, flag)); }
private static ItemDescriptor DeserializeSegment(ref JReader r) { var segment = SegmentSerialization.Instance.ReadJson(ref r) as Segment; return(segment.Deleted ? ItemDescriptor.Deleted(segment.Version) : new ItemDescriptor(segment.Version, segment)); }
/// <summary> /// Parses the user index from a JSON representation. If the JSON string is null or /// empty, it returns an empty user index. /// </summary> /// <param name="json">the JSON representation</param> /// <returns>the parsed data</returns> /// <exception cref="FormatException">if the JSON is malformed</exception> public static UserIndex Deserialize(string json) { if (string.IsNullOrEmpty(json)) { return(new UserIndex()); } var builder = ImmutableList.CreateBuilder <IndexEntry>(); try { var r = JReader.FromString(json); for (var ar0 = r.Array(); ar0.Next(ref r);) { var ar1 = r.Array(); if (ar1.Next(ref r)) { var userId = r.String(); if (ar1.Next(ref r)) { var timeMillis = r.Long(); builder.Add(new IndexEntry { UserId = userId, Timestamp = UnixMillisecondTime.OfMillis(timeMillis) }); ar1.Next(ref r); } } } } catch (Exception e) { throw new FormatException("invalid stored user index", e); } return(new UserIndex(builder.ToImmutable())); }
internal static FlagRule ReadFlagRule(ref JReader r) { string id = null; int? variation = null; Rollout?rollout = null; ImmutableList <Clause> clauses = null; bool trackEvents = false; for (var obj = r.Object(); obj.Next(ref r);) { switch (obj.Name) { case var n when n == "id": id = r.StringOrNull(); break; case var n when n == "variation": variation = r.IntOrNull(); break; case var n when n == "rollout": rollout = ReadRollout(ref r); break; case var n when n == "clauses": clauses = SerializationHelpers.ReadClauses(ref r); break; case var n when n == "trackEvents": trackEvents = r.Bool(); break; } } return(new FlagRule(variation, rollout, id, clauses, trackEvents)); }
private TestStruct ReadStruct(ref JReader r) { var obj = r.ObjectOrNull(); if (!obj.IsDefined) { return(null); } var ret = new TestStruct(); while (obj.Next(ref r)) { switch (obj.Name) { case var n when n == "str": ret.Str = r.String(); break; case var n when n == "nums": ret.Nums = ReadInts(ref r); break; case var n when n == "bool": ret.Bool = r.Bool(); break; case var n when n == "nested": ret.Nested = ReadStruct(ref r); break; } } return(ret); }
public object ReadJson(ref JReader reader) { var valid = true; var flags = new Dictionary <string, FlagState>(); for (var topLevelObj = reader.Object(); topLevelObj.Next(ref reader);) { var key = topLevelObj.Name.ToString(); switch (key) { case "$valid": valid = reader.Bool(); break; case "$flagsState": for (var flagsObj = reader.Object(); flagsObj.Next(ref reader);) { var subKey = flagsObj.Name.ToString(); var flag = flags.ContainsKey(subKey) ? flags[subKey] : new FlagState(); for (var metaObj = reader.Object(); metaObj.Next(ref reader);) { switch (metaObj.Name.ToString()) { case "variation": flag.Variation = reader.IntOrNull(); break; case "version": flag.Version = reader.IntOrNull(); break; case "trackEvents": flag.TrackEvents = reader.Bool(); break; case "debugEventsUntilDate": var n = reader.LongOrNull(); flag.DebugEventsUntilDate = n.HasValue ? UnixMillisecondTime.OfMillis(n.Value) : (UnixMillisecondTime?)null; break; case "reason": flag.Reason = EvaluationReasonConverter.ReadJsonNullableValue(ref reader); break; } } flags[subKey] = flag; } break; default: var flagForValue = flags.ContainsKey(key) ? flags[key] : new FlagState(); flagForValue.Value = LdValueConverter.ReadJsonValue(ref reader); flags[key] = flagForValue; break; } } return(new FeatureFlagsState(valid, flags)); }
internal ItemDescriptor DeserializeFromJReader(ref JReader reader) { if (_internalDeserializer is null) { throw new ArgumentException("SDK tried to deserialize a non-built-in data kind"); } return(_internalDeserializer(ref reader)); }
private List <TestStruct> ReadStructs(ref JReader r) { var ret = new List <TestStruct>(); for (var arr = r.Array(); arr.Next(ref r);) { ret.Add(ReadStruct(ref r)); } return(ret); }
private List <int> ReadInts(ref JReader r) { var ret = new List <int>(); for (var arr = r.Array(); arr.Next(ref r);) { ret.Add(r.Int()); } return(ret); }
private List <bool> ReadBools(ref JReader r) { var ret = new List <bool>(); for (var arr = r.Array(); arr.Next(ref r);) { ret.Add(r.Bool()); } return(ret); }
internal static ImmutableList <LdValue> ReadValues(ref JReader r) { var builder = ImmutableList.CreateBuilder <LdValue>(); for (var arr = r.ArrayOrNull(); arr.Next(ref r);) { builder.Add(LdValueConverter.ReadJsonValue(ref r)); } return(builder.ToImmutable()); }
public void JsonExceptionTest() { try { var v = JReader.Parse(File.ReadAllText("FilePath")); } catch { } }
internal static ImmutableList <string> ReadStrings(ref JReader r) { var builder = ImmutableList.CreateBuilder <string>(); for (var arr = r.ArrayOrNull(); arr.Next(ref r);) { builder.Add(r.String()); } return(builder.ToImmutable()); }
/// <summary> /// Advances to the next array element if any, and returns <see langword="true"/> if successful. /// </summary> /// <remarks> /// <para> /// It returns <see langword="false"/> if the <c>JReader</c> has reached the end of the array, or /// if the array was empty or null. /// </para> /// <para> /// If <c>Next</c> returns <see langword="true"/>, you can then use <see cref="JReader"/> methods /// such as <see cref="JReader.Bool"/> to read the element value. If you do not care about the /// value, simply calling <c>Next</c> again without calling a <c>JReader</c> method will discard /// the value. /// </para> /// <para> /// For more information about why <c>Next</c> requires a <c>ref</c> parameter, see /// <see cref="JReader"/>. /// </para> /// </remarks> /// <param name="reader">the original <see cref="JReader"/> (must be passed by reference)</param> /// <returns><see langword="true"/> if there is a next array element</returns> public bool Next(ref JReader reader) { if (!_defined) { return(false); } var hasNext = reader.ArrayNext(!_afterFirst); _afterFirst = true; return(hasNext); }
public object ReadJson(ref JReader reader) { try { return(ReadJsonValue(ref reader)); } catch (Exception e) { throw reader.TranslateException(e); } }
public object ReadJson(ref JReader reader) { string key = null; int version = 0; bool deleted = false; ImmutableList <string> included = null, excluded = null; ImmutableList <SegmentRule> rules = null; string salt = null; for (var obj = reader.Object().WithRequiredProperties(_requiredProperties); obj.Next(ref reader);) { switch (obj.Name) { case var n when n == "key": key = reader.String(); break; case var n when n == "version": version = reader.Int(); break; case var n when n == "deleted": deleted = reader.Bool(); break; case var n when n == "included": included = SerializationHelpers.ReadStrings(ref reader); break; case var n when n == "excluded": excluded = SerializationHelpers.ReadStrings(ref reader); break; case var n when n == "rules": var rulesBuilder = ImmutableList.CreateBuilder <SegmentRule>(); for (var rulesArr = reader.Array(); rulesArr.Next(ref reader);) { rulesBuilder.Add(ReadSegmentRule(ref reader)); } rules = rulesBuilder.ToImmutable(); break; case var n when n == "salt": salt = reader.StringOrNull(); break; } } if (key is null && !deleted) { throw new RequiredPropertyException("key", 0); } return(new Segment(key, version, deleted, included, excluded, rules, salt)); }
internal static PatchData ParsePatchData(byte[] json) { var r = JReader.FromUtf8Bytes(json); try { DataKind kind = null; string key = null; for (var obj = r.Object().WithRequiredProperties(_patchRequiredProperties); obj.Next(ref r);) { if (obj.Name == "path") { TryParsePath(r.String(), out kind, out key); if (kind is null) { // An unrecognized path isn't considered an error; we'll just return a null kind, // indicating that we should ignore this event. return(new PatchData(null, null, new ItemDescriptor())); } } else if (obj.Name == "data") { if (kind != null) { // If kind is null here, it means we happened to read the "data" property before // the "path" property, so we don't yet know what kind of data model object this // is, so we can't parse it yet and we'll have to do a second pass. var item = kind.DeserializeFromJReader(ref r); return(new PatchData(kind, key, item)); } } } // If we got here, it means we couldn't parse the data model object yet because we saw the // "data" property first. But we definitely saw both properties (otherwise we would've got // an error due to using WithRequiredProperties) so kind is now non-null. var r1 = JReader.FromUtf8Bytes(json); for (var obj = r1.Object(); obj.Next(ref r1);) { if (obj.Name == "data") { return(new PatchData(kind, key, kind.DeserializeFromJReader(ref r1))); } } throw new RequiredPropertyException("data", json.Length); } catch (Exception e) { throw r.TranslateException(e); } }
public void JsonCorrectExceptionTest() { try { var v = JReader.Parse(File.ReadAllText("FilePath")); } catch (IOException ex) { //Chyba v načítání souboru } catch (JsonException ex) { //Chyba ve formátu souboru } }
private static FullDataSet <ItemDescriptor> ParseJson(ref JReader r, int version) { var flagsBuilder = ImmutableList.CreateBuilder <KeyValuePair <string, ItemDescriptor> >(); var segmentsBuilder = ImmutableList.CreateBuilder <KeyValuePair <string, ItemDescriptor> >(); for (var obj = r.Object(); obj.Next(ref r);) { switch (obj.Name.ToString()) { case "flags": for (var subObj = r.ObjectOrNull(); subObj.Next(ref r);) { var key = subObj.Name.ToString(); var flag = FeatureFlagSerialization.Instance.ReadJson(ref r) as FeatureFlag; flagsBuilder.Add(new KeyValuePair <string, ItemDescriptor>(key, new ItemDescriptor(version, FlagWithVersion(flag, version)))); } break; case "flagValues": for (var subObj = r.ObjectOrNull(); subObj.Next(ref r);) { var key = subObj.Name.ToString(); var value = LdValueConverter.ReadJsonValue(ref r); var flag = FlagWithValue(key, value, version); flagsBuilder.Add(new KeyValuePair <string, ItemDescriptor>(key, new ItemDescriptor(version, flag))); } break; case "segments": for (var subObj = r.ObjectOrNull(); subObj.Next(ref r);) { var key = subObj.Name.ToString(); var segment = SegmentSerialization.Instance.ReadJson(ref r) as Segment; segmentsBuilder.Add(new KeyValuePair <string, ItemDescriptor>(key, new ItemDescriptor(version, SegmentWithVersion(segment, version)))); } break; } } return(new FullDataSet <ItemDescriptor>(ImmutableList.Create <KeyValuePair <DataKind, KeyedItems <ItemDescriptor> > >( new KeyValuePair <DataKind, KeyedItems <ItemDescriptor> >(DataModel.Features, new KeyedItems <ItemDescriptor>(flagsBuilder.ToImmutable())), new KeyValuePair <DataKind, KeyedItems <ItemDescriptor> >(DataModel.Segments, new KeyedItems <ItemDescriptor>(segmentsBuilder.ToImmutable())) ))); }
internal static Rollout?ReadRollout(ref JReader r) { ImmutableList <WeightedVariation> variations = null; UserAttribute?bucketBy = null; var obj = r.ObjectOrNull(); if (!obj.IsDefined) { return(null); } while (obj.Next(ref r)) { switch (obj.Name) { case var n when n == "variations": var listBuilder = ImmutableList.CreateBuilder <WeightedVariation>(); for (var arr = r.ArrayOrNull(); arr.Next(ref r);) { int variation = 0, weight = 0; for (var wvObj = r.Object(); wvObj.Next(ref r);) { switch (wvObj.Name) { case var nn when nn == "variation": variation = r.Int(); break; case var nn when nn == "weight": weight = r.Int(); break; } } listBuilder.Add(new WeightedVariation(variation, weight)); } variations = listBuilder.ToImmutable(); break; case var n when n == "bucketBy": var s = r.StringOrNull(); bucketBy = s is null ? (UserAttribute?)null : UserAttribute.ForName(s); break; } } return(new Rollout(variations, bucketBy)); }
// Currently there is only one serialization schema, but it is possible that future // SDK versions will require a richer model. In that case we will need to design the // serialized format to be distinguishable from previous formats and allow reading // of older formats, while only writing the new format. internal static FullDataSet DeserializeV1Schema(string serializedData) { var builder = ImmutableList.CreateBuilder <KeyValuePair <string, ItemDescriptor> >(); var r = JReader.FromString(serializedData); try { for (var or = r.Object(); or.Next(ref r);) { var flag = FeatureFlagJsonConverter.ReadJsonValue(ref r); builder.Add(new KeyValuePair <string, ItemDescriptor>(or.Name.ToString(), flag.ToItemDescriptor())); } } catch (Exception e) { throw new InvalidDataException(ParseErrorMessage, r.TranslateException(e)); } return(new FullDataSet(builder.ToImmutable())); }
internal static VariationOrRollout ReadVariationOrRollout(ref JReader r) { int? variation = null; Rollout?rollout = null; for (var obj = r.ObjectOrNull(); obj.Next(ref r);) { switch (obj.Name) { case var n when n == "variation": variation = r.IntOrNull(); break; case var n when n == "rollout": rollout = ReadRollout(ref r); break; } } return(new VariationOrRollout(variation, rollout)); }
internal static Target ReadTarget(ref JReader r) { ImmutableList <string> values = null; int variation = 0; for (var obj = r.Object(); obj.Next(ref r);) { switch (obj.Name) { case var n when n == "values": values = SerializationHelpers.ReadStrings(ref r); break; case var n when n == "variation": variation = r.Int(); break; } } return(new Target(values, variation)); }