private static void SkipAsArray(JsonReader reader) { var part = new BufferPart(); var firstPass = true; while (true) { var token = reader.Read(ref part, out var _); if (token == JsonToken.ArrayEnd && firstPass) { return; } SkipFromCurrent(reader, token); token = reader.Read(ref part, out var _); if (token == JsonToken.ArrayEnd) { return; } if (token != JsonToken.ValueSeparator) { throw Exceptions.BadToken(reader, token, JsonToken.ValueSeparator); } firstPass = false; } }
public static void SkipNext(JsonReader reader) { var part = new BufferPart(); var token = reader.Read(ref part, out var _); SkipFromCurrent(reader, token); }
private static void SkipAsObject(JsonReader reader) { var part = new BufferPart(); var firstPass = true; while (true) { var token = reader.Read(ref part, out var _); if (token == JsonToken.ObjectEnd && firstPass) { return; } if (token != JsonToken.String) { throw Exceptions.BadToken(reader, token, JsonToken.String); } AssertToken(JsonToken.NameSeparator, reader, ref part); SkipNext(reader); token = reader.Read(ref part, out var _); if (token == JsonToken.ObjectEnd) { return; } if (token != JsonToken.ValueSeparator) { throw Exceptions.BadToken(reader, token, JsonToken.ValueSeparator); } firstPass = false; } }
private static Func <DeserializationContext, object> ForEnum(Type type, Func <Type, TypeDescriptor> descriptorSource) { var underlyingType = Enum.GetUnderlyingType(type); var descriptor = descriptorSource(underlyingType); var enumValues = new Dictionary <string, object>(); var toUnderlying = ReflectionUtils.BuildCaster(underlyingType); foreach (var value in Enum.GetValues(type)) { enumValues[value.ToString()] = value; enumValues[toUnderlying(value).ToString()] = value; } return(context => { var reader = context.Reader; if (reader.PeekToken().HasFlag(JsonToken.Number)) { return Enum.ToObject(type, descriptor.Reader(context)); } var bufferPart = new BufferPart(); var token = reader.Read(ref bufferPart, out var text); if (token != JsonToken.String) { throw Exceptions.BadToken(reader, token, JsonToken.String | JsonToken.Number); } return enumValues.TryGetValue(text, out var value) ? value : throw new JsonException($"Unknown enum value '{text}' near line {reader.Line}, column {reader.Column}."); }); }
public static string ReadString(JsonReader reader) { var part = new BufferPart(); var token = reader.Read(ref part, out var buffer); if (token == JsonToken.Null) { return(null); } if (token == JsonToken.String) { return(buffer); } if (token.HasFlag(JsonToken.Number)) { return(part.Text.Substring(part.Start, part.Length)); } if (token == JsonToken.True) { return("true"); } if (token == JsonToken.False) { return("false"); } throw Exceptions.BadFormat(reader, "string value"); }
private static void AssertToken(JsonToken expected, JsonReader reader, ref BufferPart buffer) { var token = reader.Read(ref buffer, out var _); if (!token.HasFlag(expected)) { throw Exceptions.BadToken(reader, token, expected); } }
private static Func <DeserializationContext, object> ForCollection(Type type, Func <Type, TypeDescriptor> descriptorSource) { var element = ReflectionUtils.FindCollectionElementType(type); var constructor = ReflectionUtils.BuildConstructor(typeof(List <>).MakeGenericType(element)); var elementDescriptor = descriptorSource(element); return(context => { var reader = context.Reader; var bufferPart = new BufferPart(); var token = reader.Read(ref bufferPart, out var _); if (token == JsonToken.Null) { return null; } var target = (IList)constructor(); if (token != JsonToken.ArrayStart) { throw Exceptions.BadToken(reader, token, JsonToken.ObjectStart); } var finalizer = type.IsArray ? new Func <IList, object>(i => { var array = Array.CreateInstance(element, i.Count); i.CopyTo(array, 0); return array; }) : null; var isFirst = true; while (true) { if (reader.PeekToken() == JsonToken.ArrayEnd) { reader.Read(ref bufferPart, out var _); return finalizer != null?finalizer(target) : target; } if (!isFirst) { token = reader.Read(ref bufferPart, out var _); if (token != JsonToken.ValueSeparator) { throw Exceptions.BadToken(reader, token, JsonToken.ValueSeparator); } } var item = elementDescriptor.Reader(context); target.Add(item); isFirst = false; } }); }
private static T ParseString <T>(JsonReader reader, Func <string, T?> parser) where T : struct { var part = new BufferPart(); var token = reader.Read(ref part, out var buffer); if (token != JsonToken.String) { throw Exceptions.BadFormat(reader, "string value"); } var result = parser(buffer); return(result ?? throw Exceptions.BadFormat(reader, "string value")); }
private static T ParseNumber <T>(JsonReader reader, Func <string, T?> parser) where T : struct { var part = new BufferPart(); var token = reader.Read(ref part, out var buffer); if (token.HasFlag(JsonToken.Number)) { return(parser(part.Text.Substring(part.Start, part.Length)) ?? throw Exceptions.BadFormat(reader, "string value")); } if (token != JsonToken.String) { throw Exceptions.BadFormat(reader, "string value"); } return(parser(buffer) ?? throw Exceptions.BadFormat(reader, "string value")); }
public static bool ReadBool(JsonReader reader) { var part = new BufferPart(); var token = reader.Read(ref part, out var buffer); if (token == JsonToken.True) { return(true); } if (token == JsonToken.False) { return(false); } if (token.HasFlag(JsonToken.Number)) { if (part.Length == 1) { return(part.Text[part.Start] != '0'); } var text = part.Text.Substring(part.Start, part.Length); if (token.HasFlag(JsonToken.NumberFloat)) { return(double.TryParse(text, Base10WithExponent, CultureInfo.InvariantCulture, out var value) ? value != 0 : throw Exceptions.BadFormat(reader, "double value")); } return(long.TryParse(text, out var result) ? result != 0 : throw Exceptions.BadFormat(reader, "numeric value")); } if (token == JsonToken.String) { try { return(Convert.ToBoolean(buffer, CultureInfo.InvariantCulture)); } catch (FormatException) { throw Exceptions.BadFormat(reader, "bool value"); } } throw Exceptions.BadToken(reader, token, JsonToken.False | JsonToken.True); }
private static Func <DeserializationContext, object> ForNullable(Type underlyingType, Func <Type, TypeDescriptor> descriptorSource) { var descriptor = descriptorSource(underlyingType); return(context => { var reader = context.Reader; if (reader.PeekToken() != JsonToken.Null) { return descriptor.Reader(context); } var bufferPart = new BufferPart(); var token = reader.Read(ref bufferPart, out var _); if (token != JsonToken.Null) { throw Exceptions.BadToken(reader, token, JsonToken.Null); } return null; }); }
public static int ReadInt(JsonReader reader) { var part = new BufferPart(); var token = reader.Read(ref part, out var buffer); int value; if (token == JsonToken.String) { return(int.TryParse(buffer, out value) ? value : throw Exceptions.BadFormat(reader, "integer value")); } if (!token.HasFlag(JsonToken.Number)) { throw Exceptions.BadToken(reader, token, JsonToken.Number); } if (token.HasFlag(JsonToken.NumberFloat) || token.HasFlag(JsonToken.NumberExponent)) { throw Exceptions.BadFormat(reader, "integer value"); } return(Parsing.TryParseBase10Int(part.Text, part.Start, part.Length, out value) ? value : throw Exceptions.BadFormat(reader, "integer value")); }
public JsonToken Read(ref BufferPart bufferPart, out string buffer) { SkipWhitespace(); bufferPart.Text = _buffer.Text; bufferPart.Start = _buffer.Position; bufferPart.Length = -1; buffer = null; var current = _buffer.Peek(); if (current == '\uffff') { return(JsonToken.End); } switch (current) { case 't': ConsumeMatchingContent("true"); return(JsonToken.True); case 'f': ConsumeMatchingContent("false"); return(JsonToken.False); case 'n': ConsumeMatchingContent("null"); return(JsonToken.Null); case '"': _buffer.Advance(); buffer = ReadString(); return(JsonToken.String); case '[': _buffer.Advance(); return(JsonToken.ArrayStart); case ']': _buffer.Advance(); return(JsonToken.ArrayEnd); case '{': _buffer.Advance(); return(JsonToken.ObjectStart); case '}': _buffer.Advance(); return(JsonToken.ObjectEnd); case ':': _buffer.Advance(); return(JsonToken.NameSeparator); case ',': _buffer.Advance(); return(JsonToken.ValueSeparator); default: if (current == '-' || (current >= '0' && current <= '9')) { var numberType = ReadNumber(out var length); bufferPart.Length = length; return(JsonToken.Number | numberType); } throw new JsonException($"Unexpected token '{current}' at line {_buffer.Line}, column {_buffer.Column}."); } }
private static IEnumerable <DeferredEntry> ReadProperties(object target, DeserializationContext context, IReadOnlyDictionary <string, PropertyBinding> all) { var bufferPart = new BufferPart(); var reader = context.Reader; List <DeferredEntry> deferred = null; while (true) { var token = reader.Read(ref bufferPart, out var propertyName); if (token == JsonToken.ObjectEnd) { return(deferred); } if (token != JsonToken.String) { throw Exceptions.BadToken(reader, token, JsonToken.String); } var hasProperty = all.TryGetValue(propertyName, out var property); token = reader.Read(ref bufferPart, out var _); if (token != JsonToken.NameSeparator) { throw Exceptions.BadToken(reader, token, JsonToken.NameSeparator); } if (hasProperty) { ITypeSelector typeSelector = null; var shouldDeffer = context.TypeSelectors?.TryGetValue(property.Descriptor.Type, out typeSelector) == true; if (!shouldDeffer) { property.Setter(target, property.Descriptor.Reader(context)); } else { var entry = new DeferredEntry { Selector = typeSelector, Binding = property, Snapshot = reader.TakeSnapshot() }; ValueSkipper.SkipNext(reader); if (deferred == null) { deferred = new List <DeferredEntry>(); } deferred.Add(entry); } } else { ValueSkipper.SkipNext(reader); } token = reader.Read(ref bufferPart, out var _); if (token == JsonToken.ObjectEnd) { return(deferred); } if (token != JsonToken.ValueSeparator) { throw Exceptions.BadToken(reader, token, JsonToken.ValueSeparator); } } }
private static Func <DeserializationContext, object> ForComplex(Type type, TypeOptions options, Func <Type, TypeDescriptor> descriptorSource) { var info = type.GetTypeInfo(); if (info.IsClass && info.GetConstructor(Type.EmptyTypes) == null) { return(reader => throw new JsonException(info.IsAbstract ? $"Type {type} is abstract. Add {nameof(ITypeSelector)} to {nameof(SerializationSettings)} in order to deserialize this type." : $"Type {type} must define public parameterless constructor.")); } var properties = info .GetProperties(BindingFlags.Instance | BindingFlags.Public) .Where(i => i.SetMethod != null && i.GetMethod != null) .Select(i => new { Property = (MemberInfo)i, Setter = ReflectionUtils.BuildSetter(i), Descriptor = descriptorSource(i.PropertyType) }); var fields = info .GetFields(BindingFlags.Instance | BindingFlags.Public) .Select(i => new { Property = (MemberInfo)i, Setter = ReflectionUtils.BuildFieldSetter(i), Descriptor = descriptorSource(i.FieldType) }); var all = properties .Concat(fields) .SelectMany(i => JsonNames(i.Property).Select(j => new PropertyBinding { Name = j, Setter = i.Setter, Descriptor = i.Descriptor })) .GroupBy(i => i.Name) .ToDictionary(i => i.Key, i => i.First()); var constructor = info.IsClass ? ReflectionUtils.BuildConstructor(type) : () => Activator.CreateInstance(typeof(Box <>).MakeGenericType(type)); //struct types are internally wrapped into Box<T> type (see ReflectionUtils) var unwrapper = !info.IsClass ? new Func <object, object>(i => ((IBox)i).Value) : null; return(context => { var bufferPart = new BufferPart(); var reader = context.Reader; var token = reader.Read(ref bufferPart, out var _); if (token == JsonToken.Null) { return info.IsClass ? (object)null : throw new JsonException($"Unable to assign null value to struct type near line {reader.Line}, column {reader.Column}."); } if (token != JsonToken.ObjectStart) { throw Exceptions.BadToken(reader, token, JsonToken.ObjectStart); } var target = constructor(); var deferred = ReadProperties(target, context, all); var unwrapped = unwrapper != null?unwrapper(target) : target; if (deferred == null) { return unwrapped; } foreach (var entry in deferred) { var runtimeType = entry.Selector.FindPropertyType(entry.Binding.Name, unwrapped); var descriptor = context.Catalog.GetDescriptor(runtimeType, options); using (reader.LoadSnapshot(entry.Snapshot)) entry.Binding.Setter(target, descriptor.Reader(context)); } return unwrapper != null?unwrapper(target) : target; }); }